Compound statements disable set -e in bash
You think you know a language.
I thought I knew bash, but got completely blindsided by some quirky behavior regarding compound statements where it appears that set -e is ignored in compound statements.
As an example, what would you guess would be the output if you ran:
#!/usr/bin/env bash
set -euo pipefail
function my_fun {
ls /i/dont/exist
echo "I don't expect to be printed"
}
my_fun || { echo "An error occurred"; exit 1; }
Would you guess that it would output:
? ~ ./my_script
ls: /i/dont/exist: No such file or directory
An error occurred
Because it actually outputs:
? ~ ./my_script
ls: /i/dont/exist: No such file or directory
I don't expect to be printed
????????????
This is surprising behavior to most people I spoke to.
Including ChatGPT and Claude
Why?
The problem here appears to be to do with the way in which the set builtin works during compound statements. The documentation immediately acknowledges
This builtin is so complicated that it deserves its own section.
Which is a pretty troublesome start.
The key text can be found in the section for -e
The shell does not exit if the command that fails is ... part of any command executed in a && or || list ...
Key Takeaways
- Check the negative cases for your bash scripts to ensure they fail as you expect.
- For those of you who rely on GPTs for writing bash: buyer beware.