HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

環境変数PATHからのコマンドの探索(which,where)

唐突にバッチプログラムとして書いてみた。
一応、ご存じない方のために説明すると、UNIX/Linuxでは、以下のコマンドが提供されていたりする(環境依存)。

  • which
    • 環境変数PATHから指定したコマンドを探し出し、そのフルパスを出力する。
    • 一つ見つかった時点で終了する。
  • where
    • 環境変数PATHから指定したコマンドを探し出し、そのフルパスを出力する。
    • PATHにセットされているすべてのディレクトリに対して試行する。


なお、確認環境はWindows Vista Business(32bit版)のみなので、他で動かなかったら‥ゴメンナサイ

which.bat

こっちは一つだけ出せばいいので比較的簡単。

@ECHO OFF

SETLOCAL

FOR %%I IN (%1.bat %1.exe %1) DO (
    IF NOT "%%~$PATH:I"=="" (
        SET f=%%~$PATH:I
    )
)

IF NOT "%f%"=="" (
    echo %f%
)

ENDLOCAL

こんな感じで使用する。

C:\> which.bat hoge

C:\> which.bat notepad
C:\Windows\System32\notepad.exe

C:\> 

where.bat

こっちはちょっと面倒。環境変数PATHのデリミタであるセミコロンで区切って順次試行‥なのだが、トークンの数が任意なので、「FOR /F」を単純に使用することはできない。
で、どうしたかというと、「先頭のディレクトリと残りに分割し、先頭のディレクトリに対して試行する」というルーチンを作り、それを「残り」がなくなるまで続けるという形で実装。

@ECHO OFF

SETLOCAL

SET p=%PATH%

:_BEGIN
CALL :_WHERE %1
IF NOT "%p%"=="" GOTO _BEGIN
GOTO _END

:_WHERE
FOR /F "tokens=1,* delims=;" %%i IN ("%p%") DO (
    IF EXIST %%i\%1 (
        ECHO %%i\%1
    ) ELSE  IF EXIST %%i\%1.exe (
        ECHO %%i\%1.exe
    ) ELSE  IF EXIST %%i\%1.bat (
        ECHO %%i\%1.bat
    )
    SET p=%%j
)
EXiT /B

:_END

ENDLOCAL

こんな感じで使用する。

C:\> where.bat hoge

C:\> where notepad
C:\Windows\system32\notepad.exe
C:\Windows\notepad.exe

C:\> 

をぉ、notepad.exeって2箇所にあるんだ‥

オチ

C:\> where.bat where
C:\Windows\system32\where.exe

C:\> 

‥‥え!?

C:\> C:\Windows\system32\where.exe notepad
C:\Windows\System32\notepad.exe
C:\Windows\notepad.exe

C:\> 

‥‥もしかしてwhereは作らなくても元からあった!?‥orz