This thread was initially about whether it is a bug or a feature, that
bash pedanticly sticks to the POSIX-sufficient requirement that 'set -e'
exit only after getting a nonzero status from a "simple command", while
the original Bourne makes a very useful generalization to "any child"
(including subshells).
I'm still interested in the answer: could some kind person please
address this issue specifically, without digressing to the (otherwise
exciting) millions of ways of avoiding a subshell, or good/bad reasons
to use 'set -e' ?...
What's the rationale after all ? The generalization is trivial to
implement, while the bash behavior has already consumed many
person-months in debugging (as witnessed by groups.google.com) !
Please...
TIA,
-Alex
I think POSIX specification is another way to formulate Bourne
shell behavior. A non-simple command is always composed of
simple commands (when it's not ("case a in; esac"), the exit
code is 0). So, whenever a non-simple command has a non-zero
exit-status, that means that a simple-command failed, so, the
shell should exit (there's no reference to subshells).
Note that POSIX is not consistant on (at least) one point:
-e
When this option is on, if a simple command fails for any of the
^^^^^^^^^^^^^^
reasons listed in Consequences of Shell Errors or returns an
exit status value >0, and is not part of the compound list
following a while, until, or if keyword, and is not a part of an
AND or OR list, and is not a pipeline preceded by the ! reserved
^^^^^^^^
word, then the shell shall immediately exit.
That would mean that a pipeline (such as "( foo ) | while ...")
is a simple command! Even though they meant "and is not part of
a pipeline...", that would mean that "false | true" should exit
the shell, as false is a simple command!
Another point not clear:
For me (as for bash, ksh or zsh), "true && false" should exit
the shell. But "false" is "part of an AND list"!
To sum up, my understanding is that bash is not POSIX compliant,
that the POSIX specification is not clear and that bsh/ksh/zsh
behavior is the right one.
So I think we mostly agree.
--
Stéphane
Because I helped mud the water with manpage, I feel compelled to
transfer my latest test result from the original thread (posted shortly
before this thread). As the OP pointed out, correctly as shown below,
the statement quoted from manpage does not apply to the body of if,
until and while loop, but only to conditionals (any part of && or ||
list is considered an expression rather than a statement, I guess).
Haven't specifically done other subshell tests, but if and while are
tested as following:
$ bash -version
GNU bash, version 2.05a.0(1)-release (i686-pc-linux-gnu)
$ bash -c "if true;then mkdir;echo Not yet;fi"
mkdir: too few arguments
Try `mkdir --help' for more information.
Not yet
$ bash -ce "while true;do mkdir;echo Not yet;done"
mkdir: too few arguments
Try `mkdir --help' for more information.
$ bash -ce "if true;then mkdir;echo Not yet;fi"
mkdir: too few arguments
Try `mkdir --help' for more information.
$ bash -c "set -e;while true;do mkdir;echo Not yet;done"
mkdir: too few arguments
Try `mkdir --help' for more information.
$ bash -c "set -e;if true;then mkdir;echo Not yet;fi"
mkdir: too few arguments
Try `mkdir --help' for more information.
Note that mkdir exits before echo has a chance to utter "Not yet" in
both if and while when -e option or set -e command is used.
Yuan Liu
There was also a point about:
bash -ce "( mkdir );echo yet"
And:
bash -ce ": | while :; do mkdir; done;echo yet"
--
Stéphane