Ask questionsSC2181 suggests to check exit code directly when I check for several possible values

  • Rule Id: SC2181
  • My shellcheck version: 0.4.7
  • [x] I tried on and verified that this is still a problem on the latest commit
  • [ ] It's not reproducible on, but I think that's because it's an OS, configuration or encoding issue

Here's a snippet that shows the problem:

#!/usr/bin/env bash

gzip --test "$1"
if [[ $? -eq 0 || $? -eq 2 ]]
    echo ok
    echo bad

Here's what shellcheck currently says:

In line 4: if [[ $? -eq 0 || $? -eq 2 ]] ^-- SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.

Here's what I wanted or expected to see:

Nothing, because the successful operation is not the only exit code I'm testing against. gzip possible exit statuses:

Exit status is normally 0; if an error occurs, exit status is 1. If a warning occurs, exit status is 2.

I want to test for both normal and warning, i.e. any of 0 and 2. And the remaining exit status - 1 falls into the else conditional path.

Moreover, shellcheck is silent for

if $? || [[ $? -eq 2 ]]

that is completely wrong. Since testing the first expression $? actually gets executed and rewrites the gzip exit code value. So that the second [[ $? -eq 2 ]] never matches.

P.S. Of course, I could test just for exit status 1 in my case, but there could be new exit statues beside 0, 1, 2 in general.


Answer questions arendtio

@koalaman I think I wasn't precise enough about what the issue is: The problem I am having is that when set -e is active, the two alternatives foo; if [ $? -eq 0 ] and if foo; do not result in the same execution. So they are no alternatives, they are different programs.

Yet SC2181 suggests you can easily replace one with the other, but in reality, it depends on what foo does (and if it requires set -e to be active).


Related questions

SC1090/SC1091: sourcing should find files relative to script hot 1
Github User Rank List