Am I the only one that thinks setting -e is a huge footgun given that it only works in certain contexts? I'd much rather see explicit error handling.
set -e
i=0
(( i++ )) # shell will exit here
Still, I tend to use it because even though it doesn't handle every case, I'd still usually rather my scripts exit when a command fails. This is a terse description of the new features added
to bash-4.1 since the release of bash-4.0. [...]
j. The [[ and (( commands are now subject to the setting
of `set -e' and the ERR trap."
https://git.savannah.gnu.org/cgit/bash.git/tree/NEWS#n1078Test program:
$ cat foo.sh
#!/bin/bash
set -eux
echo "$BASH_VERSION"
i=0
(( i++ ))
echo "?=$? i=$i"
(( i++ ))
echo "?=$? i=$i"
Running with 3.2.57: $ /bin/bash foo.sh
+ echo '3.2.57(1)-release'
3.2.57(1)-release
+ i=0
+ (( i++ ))
+ echo '?=1 i=1'
?=1 i=1
+ (( i++ ))
+ echo '?=0 i=2'
?=0 i=2
Running with 5.1.16: $ /opt/homebrew/bin/bash foo.sh
+ echo '5.1.16(1)-release'
5.1.16(1)-release
+ i=0
+ (( i++ ))
So the arithmetic operation returns non-zero in both cases where it evaluates to 0, but only under bash >= 4.1 does it cause bash to terminate.The moral of the story is to be careful with arithmetic operations that might evaluate to zero, or use this:
(( operation )) || true
set -e
[[ 0 == 1 ]] && true
echo Status: $?
will print "Status: 1" but set -e
func() {
[[ 0 == 1 ]] && true
}
func
echo Status: $?
will print nothing but exit after func returns.http://redsymbol.net/articles/unofficial-bash-strict-mode/
Basically, when you short circuit, it will not cause the script to exit. However, the short circuit still affects the return value of the function, or the script itself if it's the last line of the script.
So your short circuit is causing the function to return non-zero, which then causes the script to exit.
The || operator does that pretty well.