最終回は残りの部分。1回目の仕様で書いた、
(5) PATHをサーチして見つけた最初の実行ファイルのフルパスを環境変数「 _ 」にセットする
の部分であるが、最後なので全文を掲載する。例によってインデントは2バイト空白なのでコピーペーストする人は注意。
PATHをサーチして見つけた部分ということで、20-22行および28-30行である。最初かどうかは、最初に02行で _ を未定義にしておいて、if not definedで調べている。endlocal/setlocalについては7/24:setlocalしたスクリプトから外部の環境変数をセットも参照のこと。
このスクリプトで使用しているローカル変数はBLTだけであるが、12行目の%BLT%の置換は08行のfor文の時点で行われるため、08行目の後にendlocalを1回だけ書いておいても良い。実は2回目以降のsetlocalは不要である。
01 @echo off 02 set _= 03 setlocal 04 set BLT=ASSOC BREAK CALL CD CHDIR CLS COLOR COPY DATE DEL DIR ECHO 05 set BLT=%BLT% ENDLOCAL ERASE EXIT FOR FTYPE GOTO IF MD MKDIR MOVE 06 set BLT=%BLT% PATH PAUSE POPD PROMPT PUSHD RD REM REN RENAME RMDIR 07 set BLT=%BLT% SET SETLOCAL SHIFT START TIME TITLE TYPE VER VERIFY VOL 08 for %%X in (%*) do ( 09 for /f "delims=" %%A in ('DOSKEY /MACROS') do ( 10 for /f "delims==" %%B in ("%%A") do if /i "%%B" == "%%X" echo %%A 11 ) 12 for %%A in (%BLT%) do if /i "%%X" == "%%A" echo %%X cmd.exe builtin 13 if not "%%~xX" == "" if exist %%X if not exist %%~sX\NUL echo %%~X 14 for %%S in (%PATHEXT%) do if exist %%X%%S if not exist %%~sX%%S\NUL echo %%~X%%S 15 if "%%~X" == "%%~nxX" ( 16 for %%P in ("%PATH:;=";"%") do ( 17 if not "%%~xX" == "" if exist %%P\%%X ( 18 for /f "delims=" %%W in ("%%~P\%%~X") do if not exist %%~sW\NUL ( 19 echo %%~P\%%~X 20 endlocal 21 if not defined _ set _=%%~P\%%~X 22 setlocal 23 ) 24 ) 25 for %%S in (%PATHEXT%) do if exist %%~sP\%%X%%S ( 26 for /f "delims=" %%W in ("%%~P\%%~X%%S") do if not exist %%~sW\NUL ( 27 echo %%~P\%%~X%%S 28 endlocal 29 if not defined _ set _=%%~P\%%~X%%S 30 setlocal 31 ) 32 ) 33 ) 34 ) 35 ) 36 endlocal 37 if not defined _ goto :eof 38 if not "%_%" == "%_: =%" set _="%_%"
37行で、_ が未定義か判断してそうなら終了している。
38行で、_ に空白が含まれているかを判断して、そうなら " " で囲っている。空白を含むかの判断は、: 修飾子で空白を削除して元の値と等しいかどうかで行っている。
この2行は、
if defined _ if not "%_%" == "%_: =%" set _="%_%"
と1行で書けそうである。しかし、環境変数が未定義のときの : 修飾子の振る舞いからこれは構文エラーとなる。遅延環境変数を使って、
if defined _ if not "!_!" == "!_: =!" set _="!_!"
と書けば問題ないが、スクリプト中で遅延を有効にできるのはsetlocalコマンドしかないので、かえって長くなってしまう。
環境変数未定義時の : 修飾子の振る舞いはいまいちよくわからないので、いずれ調べてみる。
以上で連載は終わりである。
いよいよネタが無いので、ネタ求む。トリビアの種と違って賞品は出ないが。