ERRORLEVEL in FOR?

  • Thread starter Thread starter GrayB
  • Start date Start date
G

GrayB

Hi all,
Hmnn the ERRORLEVEL variable don't work within a FOR loop, right? Or
did I get the syntax wrong. For example:


-----------------------------
@echo off
setlocal

FOR /L %%i in (1,1,10) do (
ping -n 1 10.10.10.%%i | find /i "Reply" > NUL
echo [%ERRORLEVEL%]
)
-----------------------------

that %ERRORLEVEL% is always NUL, as in nothing. This variable holds
the expect value if I do the test without the FOR loop as just:

-------------------------
ping -n 1 10.10.10.%%i | find /i "Reply" > NUL
echo [%ERRORLEVEL%]
-------------------------

where the result is consistently [0] for success and [1] for failure.


Thanks all!
 
GrayB said:
Hi all,
Hmnn the ERRORLEVEL variable don't work within a FOR loop, right? Or
did I get the syntax wrong. For example:


-----------------------------
@echo off
setlocal

FOR /L %%i in (1,1,10) do (
ping -n 1 10.10.10.%%i | find /i "Reply" > NUL
echo [%ERRORLEVEL%]
)
-----------------------------

that %ERRORLEVEL% is always NUL, as in nothing. This variable holds
the expect value if I do the test without the FOR loop as just:

-------------------------
ping -n 1 10.10.10.%%i | find /i "Reply" > NUL
echo [%ERRORLEVEL%]
-------------------------

where the result is consistently [0] for success and [1] for failure.


Thanks all!

The syntax is right, and it has nothing to do with ERRORLEVEL in particular.
It is a result of how CMD itself executes the code. CMD regards everything
in parentheses as a single 'chunk', and it resolves all of the variables
(in this case, ERRORLEVEL) *before* executing the statement(s) of which the
'chunk' is comprised. So, of course, before the 'echo [%ERRORLEVEL%]'
statement has ever been executed once, '%ERRORLEVEL%' has already resolved
to '0'.

If you are using Win2000 or later, then you can get around this by

setlocal ENABLEDELAYEDEXPANSION

and

echo [!ERRORLEVEL!]
 
Yes, all of that is true. However, if the ERRORLEVEL is
tested, rather than the Errorlevel variable, the test does
not depend on evar expansion, say something like this ...

@echo off
FOR /L %%i in (1,1,10) do (
ping -n 1 10.10.10.%%i | find /i "TTL=" > nul
if not errorlevel 1 echo %%i: [0]
if errorlevel 1 echo %%i: [1]
)

The other common approach, that works in NT4 as well, is
to form a subroutine and call it from the FOR ...

@echo off
FOR /L %%i in (1,1,10) do call :Sub %%i
goto :EOF

:Sub
ping -n 1 10.10.10.%1 | find /i "TTL=" > nul
echo %1: [%ERRORLEVEL%]

BTW, I changed the match string in the find, since "Reply"
is not a robust method when used behind a firewall.

Tom Lavedas
===========
-----Original Message-----
GrayB said:
Hi all,
Hmnn the ERRORLEVEL variable don't work within a FOR loop, right? Or
did I get the syntax wrong. For example:


-----------------------------
@echo off
setlocal

FOR /L %%i in (1,1,10) do (
ping -n 1 10.10.10.%%i | find /i "Reply" > NUL
echo [%ERRORLEVEL%]
)
-----------------------------

that %ERRORLEVEL% is always NUL, as in nothing. This variable holds
the expect value if I do the test without the FOR loop as just:

-------------------------
ping -n 1 10.10.10.%%i | find /i "Reply" > NUL
echo [%ERRORLEVEL%]
-------------------------

where the result is consistently [0] for success and [1] for failure.


Thanks all!

The syntax is right, and it has nothing to do with ERRORLEVEL in particular.
It is a result of how CMD itself executes the code. CMD regards everything
in parentheses as a single 'chunk', and it resolves all of the variables
(in this case, ERRORLEVEL) *before* executing the statement(s) of which the
'chunk' is comprised. So, of course, before the 'echo [% ERRORLEVEL%]'
statement has ever been executed once, '%ERRORLEVEL%' has already resolved
to '0'.

If you are using Win2000 or later, then you can get around this by

setlocal ENABLEDELAYEDEXPANSION

and

echo [!ERRORLEVEL!]



--
Phil Robyn
Univ. of California, Berkeley

u n z i p m y a d d r e s s t o s e n d e - m a i l

.
 
Mark said:
If you are using Win2000 or later, then you can get around this by

setlocal ENABLEDELAYEDEXPANSION

and

echo [!ERRORLEVEL!]


Thanks!
That's such a useful tip that I dug up this detailed explanation:
http://www.jsiinc.com/SUBG/TIP3200/rh3240.htm

If you type 'SET /?' at the CMD prompt, you will see pretty much the same
information (this is what Jerrold's tip rh3240 is based on):

.....................................................................
Finally, support for delayed environment variable expansion has been
added. This support is always disabled by default, but may be
enabled/disabled via the /V command line switch to CMD.EXE. See CMD /?

Delayed environment variable expansion is useful for getting around
the limitations of the current expansion which happens when a line
of text is read, not when it is executed. The following example
demonstrates the problem with immediate variable expansion:

set VAR=before
if "%VAR%" == "before" (
set VAR=after;
if "%VAR%" == "after" @echo If you see this, it worked
)

would never display the message, since the %VAR% in BOTH IF statements
is substituted when the first IF statement is read, since it logically
includes the body of the IF, which is a compound statement. So the
IF inside the compound statement is really comparing "before" with
"after" which will never be equal. Similarly, the following example
will not work as expected:

set LIST=
for %i in (*) do set LIST=%LIST% %i
echo %LIST%

in that it will NOT build up a list of files in the current directory,
but instead will just set the LIST variable to the last file found.
Again, this is because the %LIST% is expanded just once when the
FOR statement is read, and at that time the LIST variable is empty.
So the actual FOR loop we are executing is:

for %i in (*) do set LIST= %i

which just keeps setting LIST to the last file found.

Delayed environment variable expansion allows you to use a different
character (the exclamation mark) to expand environment variables at
execution time. If delayed variable expansion is enabled, the above
examples could be written as follows to work as intended:

set VAR=before
if "%VAR%" == "before" (
set VAR=after
if "!VAR!" == "after" @echo If you see this, it worked
)

set LIST=
for %i in (*) do set LIST=!LIST! %i
echo %LIST%
......................................................................
 
If you type 'SET /?' at the CMD prompt, you will see pretty much the same
information (this is what Jerrold's tip rh3240 is based on)...

True enough, but I like the fact that Jerrold gathered together all
three ways to enable delayed expansion: by CMD switch, registry and
SETLOCAL.
 
AWESOME man you guys!

Always something new still to learn :-)

Many thanks for the invaluable tips.

Best regards.

If you type 'SET /?' at the CMD prompt, you will see pretty much the same
information (this is what Jerrold's tip rh3240 is based on)...

True enough, but I like the fact that Jerrold gathered together all
three ways to enable delayed expansion: by CMD switch, registry and
SETLOCAL.
 
Back
Top