Search code examples
unixposixshdash-shell

Weird behavior in sh with `set -e` and a subshell


The code below prints Continuing if I remove the subshell. With the subshell, I need another succesful call after the test (using : as a succesful no-op command is most straightforward, IMO) if I want to get to the Continuing part.

#!/bin/sh
set -e #Exit on untested error
( #Subshell
    #Some succesfful commands go here
    #And here comes a file test
    [ -f "doesntExist" ] && {
        : #Irrelevant
    }
    #: 
)
echo Continuing

Is this behavior correct? Why does introducing a subshell change the behavior of

[ -f "doesntExist" ] && {
      : 
}

I'm using the dash 0.5.7-2ubuntu2 to run this.


Solution

  • This is expected. set -e ignores a non-zero exit status from an AND-list, but not from a subshell. The difference between

    set -e
    [ -f "doesntExist" ] && {
        : #Irrelevant
    }
    echo Continuing
    

    and

    set -e
    ( [ -f "doesntExist" && { : ; } )
    echo Continuing
    

    is that in the former, your script sees an AND-list with a non-zero exit status, but in the latter it sees a subshell with a non-zero exit status.