windowsbatch-file

Error codes seemingly ignored by '&&' on Windows command prompt


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)


Solution

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