ERRORLEVEL in FOR?

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!
 
P

Phil Robyn

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!]
 
T

Tom Lavedas

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

.
 
P

Phil Robyn

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%
......................................................................
 
M

Mark R. Blain

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.
 
G

GrayB

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top