http://www.perlmonks.org?node_id=867810


in reply to One Bizarre Perl Problem

First off, love your new sig - 'Swiss Army Nerd Idiot' ;-)

I use Windows (XP with Activestate 5.10.1) all the time for my Perl development. I believe when Windows gets a program name without extension (your example was 'perl'), the 'search' is similar to the following pseudo-code:

PROGRAM = perl PATH = '.' + %PATH% foreach PATH in %PATH% { foreach EXTENSION in %PATHEXT% { TRY PATH\perl.EXTENSION } }

That is to say, search the local directory first, even if it isn't in your path (you won't see '.' when you type 'path' from cmd.exe). Try appending each extension in the %PATHEXT% environment variable to the program name and search current directory followed by each directory in your path.

Values of %PATH% and %PATHEXT% can be found by:

C:\> set PATH

This is *WAY* beyond Perl scope, but a nifty batch file I found and modified (I would give credit if only I remembered where I found this, Google 'which.bat' and a few different sites with different versions of this come up) acts much like the 'which' command on Unix. Save as 'which.bat' and put it in a directory in your %PATH% environment variable.

@echo off setlocal REM REM Help REM if {%1}=={/?} goto HELP if {%1}=={--help} goto HELP REM REM Check args REM if {%1}=={} goto SYNTAX_ERROR if not {%3}=={} goto SYNTAX_ERROR REM REM Start Get ARGS REM :ARGS if {%1}=={} goto EXECUTE set string=%1 REM REM If the first character in arg is a -, it's a switch REM if "!string:~0,1!"=="-" ( set position=0 :LOOP REM REM If the character indicated by the string is a space, ech +o a return; REM else, just echo the character REM if "!string:~%position%,1!"=="" goto SLIDE if "!string:~%position%,1!"=="a" set WHICHALL=YES&& goto INCR if "!string:~%position%,1!"=="-" goto INCR echo %0: unknown option -- "!string:~%position%,1!" :INCR REM REM Increment the position in the string and loop REM set /a position=%position%+1 goto LOOP ) else set batchparams=%1 :SLIDE shift goto ARGS REM ------------------------------------------------------- :EXECUTE set errorlevel_=0 set program_=%batchparams% :: Any input with wildcard or path characters is a syntax error. for /F %%i in ('echo ":" ^& echo "\" ^& echo "*" ^& echo "/" ^& echo " +?" ^& echo "," ^& echo ";"') do ( echo %program_% | find %%i > nul && goto SYNTAX_ERROR ) :: This variable stores the current directory, followed by PATH, as :: the search order to search for program files. Quotes are added :: between each ';' to handle paths with spaces. set path_="%cd%";"%PATH:;=";"%" :: Lowercase the path extensions. This is needed to perform :: case-insensitive extension comparisons. set path_ext_=%PATHEXT% set path_ext_=%path_ext_:A=a% set path_ext_=%path_ext_:B=b% set path_ext_=%path_ext_:C=c% set path_ext_=%path_ext_:D=d% set path_ext_=%path_ext_:E=e% set path_ext_=%path_ext_:F=f% set path_ext_=%path_ext_:G=g% set path_ext_=%path_ext_:H=h% set path_ext_=%path_ext_:I=i% set path_ext_=%path_ext_:J=j% set path_ext_=%path_ext_:K=k% set path_ext_=%path_ext_:L=l% set path_ext_=%path_ext_:M=m% set path_ext_=%path_ext_:N=n% set path_ext_=%path_ext_:O=o% set path_ext_=%path_ext_:P=p% set path_ext_=%path_ext_:Q=q% set path_ext_=%path_ext_:R=r% set path_ext_=%path_ext_:S=s% set path_ext_=%path_ext_:T=t% set path_ext_=%path_ext_:U=u% set path_ext_=%path_ext_:V=v% set path_ext_=%path_ext_:W=w% set path_ext_=%path_ext_:X=x% set path_ext_=%path_ext_:Y=y% set path_ext_=%path_ext_:Z=z% :: If the program name has an extension, we want to verify that the :: extension is one of those in the path_ext_ environment variable. :: If it is, then this script will only search for that program with :: that specific extension. If not, all of the extensions in the :: path_ext_ variable will be tested, appended to the program name. :: Get the extension if any from the program name. for /F %%i in ("%program_%") do (set extension_=%%~xi) :: Comparing the program extension against the list of executable :: extensions. If the extension is found, then path_ext_ will just :: have that extension. set path_ext_=%path_ext_:;= % if not {%extension_%}=={} ( for %%i in (%path_ext_%) do if "%%i"=="%extension_%" ( set path_ext_=%extension_% for /F %%i in ("%program_%") do (set program_=%%~ni) ) ) :: This will prepend a path prefix to the program name and append an :: executable extension for every path and extension found in the :: path_ and path_ext_ variables. for %%i in (%path_%) do ( for %%j in (%path_ext_%) do ( if exist "%%~i\%program_%%%~j" ( set found_=%%~i\%program_%%%~j if {%WHICHALL%}=={YES} echo !found_! if not {%WHICHALL%}=={YES} goto FOUND ) ) ) if "%found_%"=="" echo '%batchparams%' not found. goto END :FOUND echo %found_% goto END :SYNTAX_ERROR echo which: The syntax of the command is incorrect. 1>&2 goto ERROR :ERROR set errorlevel_=1 :END exit /B %errorlevel_% :HELP echo. echo %0 will find the program file that is used when run from echo a DOS prompt. It will search the current directory and the echo PATH environment variable directories for the program using echo the extensions found in the PATHEXT environment variable. echo. echo USAGE: echo. echo %0 [options] ^<program^> echo. echo -a Print all matches in order; don't stop at first +. echo. echo program An external command, program, or script. echo. echo If you want to find a program with a particular extension, echo include that extension in the program name and the 'which' echo command will only search for a program file with that extensi +on. echo.

Now, from cmd.exe:

\\vmware-host\Shared Folders Z:\mvincent\tmp> which perl Z:\mvincent\tmp\perl.bat \\vmware-host\Shared Folders Z:\mvincent\tmp> which -a perl Z:\mvincent\tmp\perl.bat C:\Perl\bin\perl.exe