I have some Batch scripts I use for automating application build processes, most of which involve chaining commands together using the &&
operator. Admittedly, I'm more experienced with Linux, but based on that experience some_command && other_command
should result in other_command
being run iff some_command
returns an exit code of 0. This answer and this answer seem to agree with that. However this appears not to be the case on Windows cmd.exe, all of the scripts run regardless of the error code of the previous.
I decided to make a simple test for this to convince myself I wasn't going insane. Consider this test.bat
, which returns an exit code of 1:
@echo off
EXIT /B 1
Running test.bat && echo This shouldn't print
prints 'This shouldn't print'. But since the exit code is clearly 1, echo
should not be called. I've tested that the error code was actually 1 using the %errorlevel%
variable, they're coming out as expected (0 before I run the script, 1 after).
On Linux I tried the same thing. Here's test.sh
:
#!/bin/bash
exit 1
Running ./test.sh && echo "This shouldn't print"
gives no output, exactly what I expected.
What's going on here?
(Note: OS is Windows 7 Enterprise)
You need to use call
to run the batch script, like this:
call test.bat && echo This shouldn't print
Without call
, the &&
operator does not receive the ErrorLevel
returned by the batch script.
When you run a batch file from within another one, you need to use call
in order to return to the calling batch file; without call
, execution terminates as soon as the called batch file has finished...:
call test.bat
echo This is going to be displayed.
...but:
test.bat
echo You will never see this!
When running test.bat
is involved in a command line where multiple commands are combined (using the concatenation operator &
, the conditional ones &&
and ||
, or even a block of code within parentheses ()
), all the commands following test.bat
are executed even if call
was not used. This is because the entire command line/block has already been parsed by the command interpreter.
However, when call
is used, the ErrorLevel
value returned by the batch file is received (which is 1
in our situation) and the following commands behave accordingly:
call test.bat & echo This is always printed.
echo And this is also always printed.
call test.bat && echo This is not printed.
call test.bat || echo But this is printed.
(
call test.bat
echo This is printed too.
echo And again this also.
)
call test.bat & if ErrorLevel 1 echo This is printed.
But without call
you will get this...:
test.bat & echo This is printed.
echo But this is not!
...and...:
test.bat && echo Even this is printed!
echo Neither is this!
...and...:
test.bat || echo But this is not printed!
echo And this is not either!
...and:
(
call test.bat
echo This is printed.
echo And this as well.
)
It seems that the &&
and ||
operators receive an ErrorLevel
of 0
-- even in case ErrorLevel
has already been set before test.bat
is executed, strangely. Also when if ErrorLevel
is used, the behaviour is similar:
test.bat & if ErrorLevel 1 echo This is not printed!
...and...:
set = & rem This constitutes a syntax error.
test.bat & if ErrorLevel 1 echo This is still not printed!
Note that the commands behind test.bat
execute after the batch script, even without call
.