Variable setting exhibits unexpected behavior when set inside for loop

184 views Asked by At

I am modifying a batch script to pass a file location to a makefile (run with nmake). The for loop is supposed to loop over available drives and search for the file if it hasn't been previously set. Batch isn't something I have much experience with, so hopefully someone can spot what's going on.

When I set winbison outside of the for loop that iterates over the drives, the variables get set with the path to win_bison.exe. When I set it inside the for loop, I get "ECHO is on". I thought that was a sympton of how batch handles parsing/expansion. I set EnableDelayedExpansion but got the same result.

Here is my code.

@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.
1

There are 1 answers

3
JosefZ On BEST ANSWER

Next script could work:

@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

In above code snippet:

  • quotes in all set "variable=value" to avoid (accidentally forgotten) trailing spaces;
  • if exist %%iNUL to avoid possible The device is not ready error message;
  • right syntax if not defined winbison etc.;
  • !variable! instead of %variable% where necessary (read EnableDelayedExpansion);
  • pushd ... popd pair used instead of cd /D.