Search code examples
windowsbatch-filefor-loopnested-loops

Batch nested for loops returns incorrect value


problem in my script is return values when indexing files of directory. In first for I need to loop my array and second for looking for file in directory. Return value is still without change and shows latest value in all variables. Yes I know, it maybe because I use setx but with set only it doesn't work absolutely.

for /L %%G in (1,1,%i%) do (
  if NOT {arch}=={32} (
    setx DriverPath !DefaultPath!driver\!DriverPath64[%%G]! >nul 2>&1
  ) else (
    setx DriverPath !DefaultPath!driver\!DriverPath32[%%G]! >nul 2>&1
  )

  :: looking for inf file
  for /r "%DriverPath%\" %%f in (*.inf) do (
    set PrinterDriverInf[%%G]=%%f
  )
)

Solution

    1. Why are you using setx? Is the normal set command not sufficient? Note that setx does not change variables for the current cmd instance.
    2. The if not statement will always evaluate to True, because you have stated literal strings on either side of the ==. Do you mean %arch% instead of arch?
    3. You'd need delayed expansion for !DriverPath!. However, for /R cannot use delayedly expanded variables, so you must move the for /R loop into a sub-routine to be able to use immediate %-expansion, or you change to the directory temporarily and let for /R default to that (changed) current directory.
    4. Never use :: comments in parenthesised blocks, use rem instead.

    Here is the fixed code:

    setlocal EnableDelayedExpansion
    for /L %%G in (1,1,%i%) do (
        if not "%arch%"=="32" (
            setx DriverPath !DefaultPath!driver\!DriverPath64[%%G]! >nul 2>&1
            set "DriverPath=!DefaultPath!driver\!DriverPath64[%%G]!"
        ) else (
            setx DriverPath !DefaultPath!driver\!DriverPath32[%%G]! >nul 2>&1
            set "DriverPath=!DefaultPath!driver\!DriverPath32[%%G]!"
        )
        rem looking for inf file
        call :SUB PrinterDriverInf[%%G] "%DriverPath%"
    )
    endlocal
    goto :EOF
    
    :SUB    
        for /R "%~2" %%f in (*.inf) do (
            set "%~1=%%f"
        )
        goto :EOF
    

    You could even simplify the code like this:

    setlocal EnableDelayedExpansion
    if not "%arch%"=="32" set "arch=64"
    for /L %%G in (1,1,%i%) do (
        setx DriverPath !DefaultPath!driver\!DriverPath%arch%[%%G]! >nul 2>&1
        set "DriverPath=!DefaultPath!driver\!DriverPath%arch%[%%G]!"
        rem looking for inf file
        pushd "!DriverPath!" && (
            for /R %%f in (*.inf) do (
                set "PrinterDriverInf[%%G]=%%f"
            )
            popd
        )
    )
    endlocal