On Tue, Nov 17, 2020 at 09:35:35AM +0100, Pierre Colombier via Bug reports for the GNU Bourne Again SHell wrote: > I'm not sure this is actually a bug since dash act the same way but > it's quite unexpected for the average user
Agreed! The behavior of set -e is extremely surprising, and people should stop expecting it to make intuitive sense. The best way to avoid being surprised by it is to stop using it altogether. You will be much happier. > and the manual suggests it should > not act like this. It is virtually impossible to document the behavior of set -e in a way that a human brain can understand, because the behavior is so nonsensical. Can you cite a specific sentence in the manual that is incorrect? > pierre@zebulon: ~ $ (set -e ; echo A ; false ; echo B ) && echo C.$? > A > B > C.0 > > #Surprising This was alerady explained a few days ago. You've got a compound command of the form X && Y. The effect of set -e is suppressed in this compound command, except if Y fails. The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test following the if or elif reserved words, part of any command executed in a && or || list except the command following the final && or ||, any command in a pipeline but the last, or if the command's return value is being inverted with !. I am guessing you are surprised that "echo B" was executed. But the documentation says that set -e doesn't apply to "any command executed in a && or || list except [the last one]". The fact that you spawned a subshell doesn't change that. The subshell is a fork() of the script, so it inherits all of the internal knowledge of the parent process. The left hand side knows it's part of a && list and therefore doesn't honor set -e. In the example that I snipped, you replaced the subshell with an explicit "bash -c ...", which is NOT a subshell, and does not inherit the internal knowledge of the parent process. In that example, the left hand side doesn't know that it's part of a && list in a calling scope, so it doesn't know it should suppress set -e. So, you get a different result. Seriously, set -e is not a good thing. Stop using it.