Reputation: 745
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
Reputation: 27340
There are some problems cmd1 || $(($?==253 ? true : false) && cmd2
:
)
is missing after false
.$(( ... ))
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
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