Skip to content
Joachim Ansorg edited this page Oct 31, 2022 · 3 revisions

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 $? from 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 $?.

Exceptions:

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

Related resources:

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

ShellCheck

Each individual ShellCheck warning has its own wiki page like SC1000. Use GitHub Wiki's "Pages" feature above to find a specific one, or see Checks.

Clone this wiki locally