Shell – How to keep last exit status after test

exit-statusshell-scriptvariable

Is it possible to keep the last command exit status ($?) unaltered after a test?

E.g., I would like to do:

command -p sudo ...
[ $? -ne 1 ] && exit $?

The last exit $? should return the sudo exit status, but instead it always returns 0 (the exit code of the test).

Is it possible to do that without a temporary variable?

Another example to clarify further:

 spd-say "$@"
 [ $? -ne 127 ] && exit $?

In this case i want to exit only if the first command is found (exit code != 127). And i want to exit with the actual spd-say exit code (it may not be
0).

EDIT:
I forgot to mention that i prefer a POSIX-complaint solution for better portability.

I use this construct in scripts where i want to provide alternatives for the same command. For instance, see my crc32 script.

The problem with temporary variables is that they could shadow other variables, and to avoid that you must use long names, which is not good for code readability.

Best Answer

$_ will work in (at least) interactive dash, bash, zsh, ksh (though apparently not in a conditional statement as requested) and mksh shells. Of those - to my knowledge - only bash and zsh will also populate it in a scripted shell. It is not a POSIX parameter - but is fairly portable to any modern, interactive shell.

For a more portable solution you can do:

command -p sudo ...
eval '[ "$?" = 127 ] || exit '"$?"

Which basically allows you to expand the initial value for $? into the tail of the script before ever even testing its value at its head.

But anyway, since you appear to be testing whether or not the command sudo can be found in the shell's builtin -p portable path string with command, I would think you could go at it a litte more directly. Also, just to be clear, command won't test for the location of any arguments to sudo - so it is only sudo - and nothing it invokes - which is relevant to that return value.

And so anyway, if that is what you're trying to do:

command -pv sudo >/dev/null || handle_it
command -p  sudo something or another

...would work just fine as a test without any chance of errors in the command sudo runs returning in such a way that might skew the results of your test.

Related Question