Bash-4.1 expression behavior change under "set -e"
linuxscratch at gmail.com
Tue Jun 22 06:49:54 PDT 2010
grep -C 1 "[[ and ((" bash-4.1/CHANGES
j. The [[ and (( commands are now subject to the setting of `set -e' and the
c. Changed the [[ and (( compound commands to set PIPESTATUS with their exit
When a script has the 'set -e' to exit on any non-zero exit status,
and the script has an expression such as '(( foo = bar ))'
whose purpose is to set the variable foo equal to the expression bar,
bash version 4.1.0 will exit when foo becomes equal to zero
as a result of setting foo equal to bar.
Earlier versions of bash would continue to process under 'set -e'
as if there had not been a non-zero exit status.
A small test program verified the different behavior vs. earlier versions:
# save as: fooey
# usage: sh fooey [-e]
[ "$1" == "-e" ] && set $1
while (( b > -10 ));do
(( b = b - 1))
echo "$? $b"
The imaginary intent of the above test program was to print the
decreasing numbers 9 through -10 preceeded by the exit code of setting
the value. The imaginary unexpected result was the abrupt exit before
printing the number zero.
I guess the behavior change was so that they could write in the bash man page:
((expression)) ... is exactly equivalent to let "expression"
Replacing '(( b = b - 1))' with 'let b="$b - 1"' in the above performs
identically in bash version 4.1.0 whereas in previous versions there
was a variance.
To replicate the old behavior, we have been afforded the opportunity
to modify all code of that type so that it has an "or" branch which
does nothing thusly:
(( b = b - 1)) || :
An alternative is to use the thing called "Arithmetic Expansion" that
looks like $((expression)) and which does not trigger an exit when
expression becomes zero in the "set -e" situation:
b=$((b - 1))
My little mind's logical concept of setting a variable to zero
successfully is that it succeeded rather than failed.
One line of code which I noticed failing was this line in jhalfs' progress bar:
(( PREV_SEC = SEC ))
The impact was that the progress bar abruptly exited for no apparent reason.
Newer is better except always.
More information about the lfs-support