Raketenolli
Raketenolli

Reputation: 745

Consider a specific exit code not a failure and proceed

I found questions about ignoring errors in shell scripts, but they ignore any error, not just a specific one.

My use case is that in some cases my_command returns an exit code -3 (253), but that is not a real error and any &&-chained commands should execute. In case of a different exit code != 0, it should stop.

So basically I'm looking for something like

my_command || $(($?==253 ? true : false) && next_command

and I've looked at the different options of using ternary operators, but none of them seem to apply to my case.

What can I do?

Upvotes: 0

Views: 1308

Answers (3)

Socowi
Socowi

Reputation: 27340

There are some problems cmd1 || $(($?==253 ? true : false) && cmd2:

  • A ) is missing after false.
  • You don't want $(( ... )) but (( ... )). The former would execute the result of the expression (that is a number!) as a command. The latter just evaluates the expression and fails if the result is 0 and succeeds otherwise. Note that is the opposite of how exit codes work.
  • true and false are not commands here, but variables. If an undefined variable is used inside (( ... )) its value is always 0. Therefore the command ((... ? true : false)) always fails.

Here is want you could have written instead:

cmd1 || (($?==253 ? 1 : 0)) && cmd2

Test:

prompt$ true || (($?==253 ? 1 : 0)) && echo ok
ok
prompt$ false  || (($?==253 ? 1 : 0)) && echo ok
prompt$ ( exit 253; )  || (($?==253 ? 1 : 0)) && echo ok
ok

However, the ternary operator isn't really needed here. The following would be equivalent:

cmd1 || (($?==253)) && cmd2

Despite that, an if would probably be better. If you don't want to use one inline, you can write a function for that:

# allow all exit codes given as the first argument
# multiple exit codes can be comma separated 
allow() {
   ok=",$1,"
   shift
   "$@"
   [[ "$ok" = *,$?,*  ]]
}
allow 0,253 cmd1 && cmd2

Or define a wrapper just for this one command

cmd1() {
    command cmd1 "$@" || (( $? == 253 ))
}
cmd1 && cmd2

Upvotes: 3

Ivan
Ivan

Reputation: 7317

Um, like this?

my_command; (($?==0|$?==253)) && next_command

Upvotes: 0

tripleee
tripleee

Reputation: 189809

The code you have evaluates to a number (once you fix the missing closing parenthesis), which is not what you want; but you can refactor it slightly if you want to maintain the same sort of flow, at the expense of a subshell.

my_command || ( exit $(($?==253)) ) && next_command

Probably a less expensive and, all things counted, both more obvious and elegant solution is the trivial

my_command || [ $? == 253 ] && next_command

Upvotes: 1

Related Questions