问题
This question is a follow-up to Bash conditional based on exit code of command .
I understand, and have made use of the accepted answer to that question:
$ cat ./txt
foo
bar
baz
$ if ! grep -Fx bax txt &>/dev/null; then echo "not found"; fi
not found
$
But I can't figure out the syntax to pull off a seemingly simple twist to the premise: how can I write a conditional for a specific exit code of a command?
This post pointed out that grep
might fail with error code > 1; so I wanted to write the above conditional to print "not found" specifically if grep
returned error code 1. How can I write such a statement? The following don't seem to work (I'm obviously flailing):
$ # Sanity-check that grep really fails with error code 1:
$ grep -Fx bax txt &>/dev/null
$ echo $?
1
$
$
$ if grep -Fx bax txt &>/dev/null -eq 1; then echo "not found"; fi
$ if grep -Fx bax txt &>/dev/null == 1; then echo "not found"; fi
$ if grep -Fx bax txt &>/dev/null = 1; then echo "not found"; fi
$ if [ grep -Fx bax txt &>/dev/null -eq 1 ]; then echo "not found"; fi
$ if [ grep -Fx bax txt &>/dev/null == 1 ]; then echo "not found"; fi
$ if [ grep -Fx bax txt &>/dev/null = 1 ]; then echo "not found"; fi
$
Note: I'm specifically trying to avoid running the command first, then using $?
in the conditional, for the reasons pointed out by the accepted answer to the first noted post.
回答1:
If you want to respond differently to different error codes (as opposed to just success/failure, as in the linked question), you need to run the command and then check $?
to get its specific exit status:
grep -Fx bax txt &>/dev/null
if [ $? -eq 1 ]; then
echo "not found"
fi
(In my answer to the linked question, I described testing whether $?
is zero as cargo cult programming; this does not apply to checking it for specific nonzero values.)
Note that $?
is re-set for every command that runs -- including one that tests $?
from the previous command -- so if you want to do more than one thing with it you must immediately store it in a variable, then run your tests on that variable:
curl "$url"
curl_status=$?
if [ "$curl_status" -eq 6 ]; then
echo "Couldn't resolve host name"
elif [ "$curl_status" -eq 7 ]; then
echo "Couldn't connect to host"
elif [ "$curl_status" -ne 0 ]; then
echo "Some sort of error occurred; curl status was $curl_status"
fi
Note that using !
to negate the success/failure of a command effectively destroys the specific error code, because it converts all nonzero codes to the same result: zero. If you want to do the equivalent of if ! command ...
and still have access to the specific code, my favorite idiom is to use ||
and a brace group, like this:
curl "$url" || {
curl_status=$?
...
# Do error handling/reporting based on $curl_status
...
}
来源:https://stackoverflow.com/questions/62033740/bash-conditional-based-on-specific-exit-code-of-command