Windows Batch: findstr not setting ERRORLEVEL within a for loop -


can explain me why following snippet prints 0:

@echo off setlocal  /f %%i in ('cmd /c echo blah') (     echo %%i | findstr bin > nul     echo %errorlevel% ) 

while adding another, equivalent statement outside of for-loop makes print 1 1:

@echo off setlocal  echo blah | findstr bin > nul echo %errorlevel%  /f %%i in ('cmd /c echo blah') (     echo %%i | findstr bin > nul     echo %errorlevel% ) 

i'm bit of newbie batch, kinda mysterious me since 2 statements seem unrelated. appreciated, thanks!

the issue within code block (parenthesised series of statements) %var%will replaced actual value of variable @ parse time.

hin first example, %errorlevel% 0 , echoed such. in second example, 1 when for encountered, hence it replaced 1.

if want display value of environment variable may changed within loop, need 1 of 3 things:

  1. invoke setlocal enabledelayedexpansion , echo !var! instead of %var% - noting number of nested setlocal instructions can have active limited.

  2. call subroutine

  3. employ syntax-exploit.

there many, many articles delayedexpansion on so.

crudely, use (note - case largely irrelevant in batch, except case of loop-control variable (metavariable - %%i in instance)

@echo off setlocal enabledelayedexpansion  echo blah | findstr bin > nul echo %errorlevel% or !errorlevel!  /f %%i in ('cmd /c echo blah') (     echo %%i | findstr bin > nul     echo %errorlevel% or !errorlevel! ) 

another way dynamically invoke setlocal

@echo off setlocal  echo blah | findstr bin > nul echo %errorlevel% or !errorlevel! /f %%i in ('cmd /c echo blah') (     echo %%i | findstr bin > nul     setlocal enabledelayedexpansion     echo %errorlevel% or !errorlevel!     endlocal     ) 

the disadvantage of endlocal backs out changes made environment since last setlocal. note if delayedexpansion not in effect, ! no longer special character.

or, can use errorlevel in traditional manner:

@echo off setlocal  echo blah | findstr bin > nul echo %errorlevel% or !errorlevel!  /f %%i in ('cmd /c echo blah') (     echo %%i | findstr bin > nul     if errorlevel 1 (echo errorlevel 1 or greater     ) else (echo errorlevel 0     ) ) 

note looks @ run-time value of errorlevel , if errorlevel n means "if errorlevel n or greater n"

or - call subroutine:

@echo off setlocal  echo blah | findstr bin > nul echo %errorlevel% or !errorlevel! /f %%i in ('cmd /c echo blah') (     echo %%i | findstr bin > nul     call :show ) goto :eof  :show echo %errorlevel% goto :eof 

note here goto :eof (here colon important - means "go physical end-of-file"

or, special version of using subroutine - syntax-exploit

@echo off setlocal  echo blah | findstr bin > nul echo %errorlevel% or !errorlevel! /f %%i in ('cmd /c echo blah') (     echo %%i | findstr bin > nul     call echo %%errorlevel%% ) 

Comments