[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: use of set -e inside parenthesis and conditionnal second command
From: |
Greg Wooledge |
Subject: |
Re: use of set -e inside parenthesis and conditionnal second command |
Date: |
Tue, 17 Nov 2020 09:24:48 -0500 |
User-agent: |
Mutt/1.10.1 (2018-07-13) |
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.