3 SC2319
Joachim Ansorg edited this page 2022-10-31 15:27:21 +01:00

This $? refers to a condition, not a command. Assign to a variable to avoid it being overwritten.

Problematic code:

mycommand
if [ $? -ne 0 ] && [ $? -ne 14 ]
then
  echo "Command failed"
fi

or

mycommand
[ $? -gt 0 ] && exit $?

Correct code:

mycommand
ret=$?
if [ $ret -ne 0 ] && [ $ret -ne 14 ]
then
  echo "Command failed"
fi

or

mycommand || exit $?

Rationale:

ShellCheck found a $? that always refers to a condition like [ .. ], [[ .. ]], or test.

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 `?frommycommand` 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 $?.

Exceptions:

None. Note that ShellCheck does not warn if the usage of $? after [ .. ] is unconditional, as in [ -d dir ]; return $?.

  • Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!