Windows .bat文件,%〜$ PATH:1引号问题

Jim*_*hen 6 windows cmd batch-file

我在Windows 7上有一个who.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
Run Code Online (Sandbox Code Playgroud)

这棒很好用,直到我今天发现一个奇怪的行为.

有一个文件 O:\temp\pfiles (x86)\mystuff.txt,PATH有内容:

PATH=O:\temp\pfiles (x86);D:\CmdUtils
Run Code Online (Sandbox Code Playgroud)

跑步which mystuff.txt,我得到了非常明显的输出:

\mystuff.txt was unexpected at this time.
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

经过一番探讨后,我发现(x86)目录名称会导致问题.要解决方法,我必须添加引号echo,如下所示:

echo %1 is found: "%~$PATH:1"
Run Code Online (Sandbox Code Playgroud)

这种调整的缺点是显而易见的:引号被打印到屏幕上,这在程序员看来并不总是需要.

谁能帮助解释这种奇怪的行为?

我发现这个问题是因为在我的真实环境中,我有一些像C:\Program Files (x86)\Common Files\NetSarangPATH 一样的路径,它们表现出完全相同的症状.

在此输入图像描述

Rob*_*ujo 8

MS Dos是非常简单的shell实现,并且我已经发现一个DOS命令行的解释分为两个阶段:

  1. 评估当前行中的变量
  2. 对评估命令行的解释

在这种情况下,您的命令行:

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

将被解释为:

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
    )
Run Code Online (Sandbox Code Playgroud)

现在我们可以注意到这个问题(x86),即解释器会以某种方式看到这个 - 首先)关闭else语句:

) ELSE (
      echo mystuff.txt is found: O:\temp\pfiles (x86
)\mystuff.txt
)
Run Code Online (Sandbox Code Playgroud)

解决方案:在所有可能存在问题的变量周围加上"".

我通常在整个echo命令内容中加上引号,例如:

echo "%1 is found: %~$PATH:1"
Run Code Online (Sandbox Code Playgroud)