Bash: conditional based on specific exit code of command

纵然是瞬间 提交于 2021-02-11 15:59:32

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!