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 S001. Use GitHub "Pages" feature above to find a specific one, or see Checks.

Clone this wiki locally