SC2181
Joachim Ansorg edited this page Nov 12, 2021
·
12 revisions
Check exit code directly with e.g. if mycmd;, not indirectly with $?.
Problematic code:
make mytarget
if [ $? -ne 0 ]
then
echo "Build failed"
fiCorrect code:
if ! make mytarget;
then
echo "Build failed"
fiRationale:
Running a command and then checking its exit status $? against 0 is redundant.
Instead of just checking the exit code of a command, it checks the exit code of a command (e.g. [) that checks the exit code of a command.
Apart from the redundancy, there are other reasons to avoid this pattern:
- Since the command and its status test are decoupled, inserting an innocent command like
echo "make finished"aftermakewill cause theifstatement to silently start comparingecho's status instead. - Scripts that run or are called with
set -eakaerrexitwill exit immediately if the command fails, even though they're followed by a clause that handles failure. - The value of
$?is overwritten by[/[[, so you can't get the original value in the relevant then/else block (e.g.if mycmd; then echo "Success"; else echo "Failed with $?"; fi).
To check that a command returns success, use if mycommand; then ....
To check that a command returns failure, use if ! mycommand; then .... Notice that ! will overwrite $? value.
To additionally capture output with command substitution: if ! output=$(mycommand); then ...
This also applies to while/until loops.
Exceptions:
The default Solaris 10 bourne shell does not support '!' outside of the test command (if ! mycommand; then ... returns !: not found)