I think that the intro to the accepted answer (although I +1
ed for its thoroughness) is misleading and it does not explain this exact issue in the presence of set -e
. The rest below the line contains the answer. I decided to write it because I myself came here for it and first got misled.
Failed will not be printed because the exit status of the compound command is that of the last command executing in { ...; }, which is echo. The echo succeeds, so the compound command exits with an exit status of zero.
What I think should be conveyed in the first place is that here, the set -e
is disabled due to the position of the { ... }
in the AND-OR list. If one removes the || echo "Failed"
part, the compound command in { ... }
will break immediately after the failing part, not even reaching the last command of { ... }
Compare
#!/bin/bash -e
{
echo "Doing something";
false
echo "Worked";
}
prints nothing after Doing something
and returns error exit, despite (here's why the answer is wrong) being a compound command inside of { ... }
with echo
being last.
While
#!/bin/bash -e
{
echo "Doing something";
false
echo "Worked";
} || echo "Failed"
prints Worked
after Doing something
, does not invoke echo "Failed"
and returns 0 exit status.
The reason is buried in the citation (provided deeper by the accepted answer): the set -e
is disabled inside anything which is part of AND-OR command.
With trailing || echo "Failed"
, the {...}
becomes part of AND-OR command and hence stops obeying set -e
. The false
in the middle does not affect the flow, and proceeds to echo "Worked"
, it returns 0 to the AND-OR, and subsequently to the calling script.
Without trailing || echo "Failed"
, the { ... }
is itself a normal compound set of commands, it does not belong to the exceptions mentioned in POSIX, and obeys set -e
. The execution stops when false
is reached, and the flow of execution does not even reach echo "Worked"
part, returning error to the calling script.
set -e
question. – Kusalananda Sep 22 '17 at 10:25