1

In Bash blocks {} and subshells () the exit early doesn't work if there is an OR condition following it. Take for example

set -e
{ echo a; false; echo b; } || echo c 

prints

a
b

and

set -e
{ echo a; false; echo b; false;} || echo c 

prints

a
b
c

It seems to take the last executed command's exit code only. While this makes sense, given a semicolon instead of && is used, I'd expect the set -e to still make it exit on the first false and execute the error handling echo c code.

Using && instead of ; does make it work, but that makes it messy when having multiple line blocks. Adding in set -e at the start of the block/subshell also has no effect.

The reason this confuses me is because

set -e
{ echo a; false; echo b; }

prints

a

which means the exit-on-failure works when there's no || code following it. So I'd expect this to be the case with || code following it, executing it after the first failure in the block. Is there no way to achieve that without appending && after each line in the block?

8
  • 1
    That's the awkwardly expected behavior of set -e in conditionals; or else a simple if false; then echo foo; else echo bar; fi would kill the script Commented Dec 20, 2024 at 13:41
  • 2
    This is BashFAQ 105: Why doesn't set -e (or set -o errexit, or trap ERR) do what I expected? Commented Dec 20, 2024 at 13:54
  • 1
    @Fravadona, right, I meant being under the testing part of a conditional anywhere. But note that in e.g. { false; echo x; } && echo y;, the exit status of false isn't exactly checked by any conditional (since echo x runs unconditionally after the semicolon), but it's still under the left-hand side of the && so set -e doesn't kick in. It works similarly even if there's subshells or functions in between. Commented Dec 20, 2024 at 14:02
  • 2
    Anyway, the point is that it's no use expecting it to be useful. One might hope, but it's in vain. It's a FAQ exactly because it looks way more useful at first glance than it actually is. Just forget about set -e, test manually and be happier. :) Commented Dec 20, 2024 at 14:03
  • 2
    I never understood the aversion to set -e up until now. true && {false; something} behaving differently than {false; something} && true under set -e is a fantastic illustration of why to avoid it. You try to avoid the "unchecked error happened" case, but invite a complete host of corner cases not covered in a sensible way by the design of what set -e does. Commented Dec 20, 2024 at 14:37

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.