$?refers to a condition, not a command. Assign to a variable to avoid it being overwritten.
mycommand if [ $? -ne 0 ] && [ $? -ne 14 ] then echo "Command failed" fi
mycommand [ $? -gt 0 ] && exit $?
mycommand ret=$? if [ $ret -ne 0 ] && [ $ret -ne 14 ] then echo "Command failed" fi
mycommand || exit $?
ShellCheck found a
$? that always refers to a condition like
[ .. ],
[[ .. ]], or
This most commonly happens when trying to inspect
$? before doing something with it, such as inspecting it again or exiting with it, without realizing that any such inspection will also overwrite
In the first problematic example,
[ $? -ne 14 ] will never be true because it only runs after
[ $? -ne 0 ] has modified $? to be 0. The solution is to assign
mycommand to a variable so that the variable can be inspected repeatedly.
In the second problematic example,
exit $? will always
exit 0, because it only runs if
[ $? -gt 0 ] returns success and sets
$? to 0. The solution could again be to assign
$? to a variable first, or (as shown) use
mycommand || exit $? as there is no condition to overwrite
None. Note that ShellCheck does not warn if the usage of
[ .. ] is unconditional, as in
[ -d dir ]; return $?.
ShellCheck is a static analysis tool for shell scripts. This page is part of its documentation.