2013-05-13 17 views
6

私は、Windows 7上でwhich.batを持って、

@echo off 
REM This bat searches a file in PATH list to see whether a file can be found. 
REM If found, it shows the file's full path. 
REM  which.bat gcc.exe 
REM shows 
REM  gcc.exe is found: D:\GMU\MinGW2\bin\gcc.exe 
REM 
REM Note: Filename extension is significant in the search. E.g. If you run 
REM  which.bat gcc 
REM gcc.exe will not be matched. 

IF "%1" == "" goto END 

IF "%~$PATH:1" == "" (
     echo %1 is not found in any directories from PATH env-var. 
    ) ELSE (
     echo %1 is found: %~$PATH:1 
    ) 

:END 

今日は奇妙な行動を見つけるまで、このバットはうまく動作します。

はファイルO:\temp\pfiles (x86)\mystuff.txtあり、そしてPATHはコンテンツがあります。

\mystuff.txt was unexpected at this time. 

enter image description here

一部がチャンスをうかがっ後:

PATH=O:\temp\pfiles (x86);D:\CmdUtils 

which mystuff.txtを実行すると、私は非常に奇妙な出力を得ました、私はディレクトリ名の(x86)がth eの問題。この問題を回避するために、私はこのように、echoに引用符を追加する必要があります。

echo %1 is found: "%~$PATH:1" 

、このような微調整の欠点は明らかである:引用符は、常にプログラマの意見で望まれていない画面に印刷されます。

誰でもこの奇妙な行動を説明できますか?

実際の環境では、PATHにC:\Program Files (x86)\Common Files\NetSarangのようないくつかのパスがありますが、これはまったく同じ症状を示しています。

enter image description here

+0

と無害

setlocal EnableDelayedExpansion IF "%~$PATH:1" == "" ( echo %1 is not found in any directories from PATH env-var. ) ELSE ( set "found=%~$PATH:1" echo %1 is found: !found! ) 

それともあるが、私はお知らせいただきありがとうございます。 '' where.exe''は素晴らしいです。私は '' where.exe''がまだないWindows XPからwhich.batを使っています。 –

+0

良い情報...しかし、あなたが '実行可能ファイル'を探していて、拡張子を与えていないのであれば、うまくいきません... 'where.exe'を使うか、ouがlinuxにあるのか 'which'を使うかちょうどCygwinをインストールし、 'を使用して...'素晴らしい作品! – ZEE

答えて

8

MSドスは非常にシンプルなシェルの実装である、と私は考え出したように、1つのDOSコマンドラインの解釈は、2段階に分けて行く:現在の行の変数の

  1. 評価
  2. 評価されたコマンドラインの解釈

この場合、コマンドライン:

IF "%~$PATH:1" == "" (
     echo %1 is not found in any directories from PATH env-var. 
    ) ELSE (
     echo %1 is found: %~$PATH:1 
    ) 

があると解釈されるだろう:

IF "O:\temp\pfiles (x86)\mystuff.txt" == "" (
     echo mystuff is not found in any directories from PATH env-var. 
    ) ELSE (
     echo mystuff.txt is found: O:\temp\pfiles (x86)\mystuff.txt 
    ) 

今、私たちは(x86)で問題に気づくことができ、すなわちインタプリタは、このように何とかこれを見ている - 最初)は、elseステートメントを閉じます。

) ELSE (
     echo mystuff.txt is found: O:\temp\pfiles (x86 
)\mystuff.txt 
) 

ソリューション:すべての潜在的に問題のある変数を ""囲みます。

は、私は通常、たとえば、全体のエコーコマンド内容の前後に引用符を置く:

echo "%1 is found: %~$PATH:1" 
+0

本当に具体的な説明。 –

2

は私が説明を推測することができます(しませ役立つ1が):CMD.EXEのパーサは非常に賢いではない - それを%~$PATH:1の括弧で混乱します。変数を展開して)文字を見ると、それは行のclosig括弧であるとみなされます。(私はそれがコマンドの開始時にのみ重要であるので、拡張で(文字で何もしないと思う)。

')'を含む拡張が(...)コマンドグループ内にないこと、または(見つかった)引用符で囲まれていることを確認することで、この問題を回避できます。あなたが引用符をしたくないので、他の問題を回避するには、次のようになります。

@echo off 
REM This bat searches a file in PATH list to see whether a file can be found. 
REM If found, it shows the file's full path. 
REM  which.bat gcc.exe 
REM shows 
REM  gcc.exe is found: D:\GMU\MinGW2\bin\gcc.exe 
REM 
REM Note: Filename extension is significant in the search. E.g. If you run 
REM  which.bat gcc 
REM gcc.exe will not be matched. 

IF "%1" == "" goto END 

IF "%~$PATH:1" == "" (
     echo %1 is not found in any directories from PATH env-var. 
    ) ELSE (
     call :printfound %1 
    ) 

goto END 

:printfound 
echo %1 is found: %~$PATH:1 
goto :eof 

:END 

それは醜いですが、それはあなたがcmd.exeのスクリプトとしなければならない事のようなものです。

4

問題が明らかになった(Michael BurrとRobert Lujoから)ので、私は解決策を提示しようとします。

あなたは引用符が必要ですが、あなたはそれらを表示したくありません。

遅延拡大に伴い閉じ括弧が消失引用

IF "%~$PATH:1" == "" (
     echo %1 is not found in any directories from PATH env-var. 
    ) ELSE (
     for %%^" in ("") do (
     echo %1 is found: %%~"%~$PATH:1 
    ) 
    ) 
+0

EnableDelayedExpansionメソッドはあまり混乱しません。ありがとうございました。 –

+1

うわー、 '' set "found = 1" ''は '' set found = 1''と同じです。 –

関連する問題