Batch file 变量设置在for循环内部设置时会显示意外行为

Batch file 变量设置在for循环内部设置时会显示意外行为,batch-file,Batch File,我正在修改批处理脚本,以便将文件位置传递给makefile(使用nmake运行)。for循环应该在可用的驱动器上循环,并搜索以前未设置的文件。批处理不是我有很多经验的事情,所以希望有人能发现发生了什么 当我在遍历驱动器的for循环之外设置winbison时,变量将被设置为win_bison.exe的路径。当我在for循环中设置它时,我得到“ECHO已打开”。我认为这是批处理如何处理解析/扩展的一个例子。我设置了EnableDelayedExpansion,但得到了相同的结果 这是我的密码 @EC

我正在修改批处理脚本,以便将文件位置传递给makefile(使用nmake运行)。for循环应该在可用的驱动器上循环,并搜索以前未设置的文件。批处理不是我有很多经验的事情,所以希望有人能发现发生了什么

当我在遍历驱动器的for循环之外设置winbison时,变量将被设置为win_bison.exe的路径。当我在for循环中设置它时,我得到“ECHO已打开”。我认为这是批处理如何处理解析/扩展的一个例子。我设置了EnableDelayedExpansion,但得到了相同的结果

这是我的密码

@ECHO OFF
setlocal EnableDelayedExpansion
set currentDir=%cd%
set winbison=
set winflex=

set drives=
for /f "delims=" %%a in ('fsutil fsinfo drives') do @set drives=%%a

REM :~8 is to slice off "Drives: " returned by fsutil
for %%i in (%drives:~8%) do (
    chdir /d %%i
    if not defined [%winbison%] (
        set winbison=
        for /f "delims=" %%a in ('dir win_bison.exe /s /b 2^>nul') do @set winbison=%%a
    @ECHO ON
        echo test
        echo %winbison%
    @ECHO OFF
    )

    if not defined [%winflex%] (
        set winflex=
        for /f "delims=" %%a in ('dir win_flex.exe /s /b 2^>nul') do @set winflex=%%a
    )
)

chdir /d %currentDir%

@ECHO ON
echo %winbison%
... stuff gets passed to nmake.

下一个脚本可以工作:

@ECHO OFF
setlocal enableextensions EnableDelayedExpansion
set "currentDir=%cd%"
set "winbison="
set "winflex="

set "drives="
for /f "delims=" %%a in ('fsutil fsinfo drives') do @set "drives=%%a"

REM :~8 is to slice off "Drives: " returned by fsutil
for %%i in (%drives:~8%) do (
  if exist %%iNUL (
    pushd %%i
    if not defined winbison (
      for /f "delims=" %%a in (
        'dir win_bison.exe /s /b 2^>nul') do @set "winbison=%%a"
      echo [debug] %%i winbison=!winbison!
    )

    if not defined winflex (
      for /f "delims=" %%a in (
        'dir win_flex.exe /s /b 2^>nul') do @set "winflex=%%a"
      echo [debug] %%i winflex=!winflex!
    )
    popd
  )
)

echo [debug] winbison=%winbison%
echo [debug] winflex=%winflex%

rem ... stuff gets passed to nmake
在上面的代码片段中:

  • 在所有
    中加引号设置“variable=value”
    以避免(意外忘记)尾随空格
  • 如果存在%%iNUL
    以避免可能的
    设备未就绪
    错误消息
  • 如果未定义winbison等,则使用正确语法
    
    
  • !变数而不是
    %variable%
    (如有必要)(读取)
  • pushd
    <代码>popd
  • 对,而不是
    cd/D

也许我能帮上忙。今晚我会在家里试一下,然后再转回来让你知道它是否有效。谢谢你的回复!我标记为答案,因为你的回答对我有效。最佳实践是一个很大的帮助。唯一没有立即意义的是,我发现很难搜索“if exist%%iNUL”如何帮助防止“设备未就绪”错误消息。谢谢@如果
X:
是未插入光盘的cd/DVD驱动器,或者
如果
X:
在您的系统中不存在,则系统无法找到指定的驱动器。或明显无效的路径名,例如在
目录c:\::
中给出的
“c:\::”不是可识别的设备
错误。但是,
如果存在任何内容\n无论拼写如何,所有echo present
都将起作用。那是为
NUL
是一个存在于任何现有文件夹中的文件(或类似文件的设备)。。。