How to use case statement to deal with multiple return values
Solution 1
You can't use
case $(somecommand) in ...
to test the exit status of somecommand
because the command substitution expands to the output of the command, not its exit status.
Using $(true)
doesn't work since true
doesn't produce any output on standard output.
You could do
{ somecommand; err="$?"; } || true
case $err in
0) echo success ;;
*) echo fail
esac
This will stop the script running under errexit
(-e
) from exiting.
From the bash
manual (from the description of set -e
):
The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test following the if or elif reserved words, part of any command executed in a && or || list except the command following the final && or ||, any command in a pipeline but the last, or if the command's return value is being inverted with !.
In this case, with only the possibilities to either succeed or to fail, it would be easier to just do
if somecommand; then
echo success
else
echo fail
fi
Solution 2
The syntax
`command`
means to substitute the standard output of the command into the original command line. The output is not the same thing as the exit status. The true
command doesn't produce any output, so your command is equivalent to:
case "" in
0) echo success ;;
*) echo fail ;;
esac
You can solve your problem this way:
case `my_command; echo $?` in
...
esac
BTW, in the if
command you don't need the backticks, it should just be:
if true
then echo successs
else echo fail
fi
Solution 3
Even with set -e
you can still do:
if my_command
then
echo success
else
res=$?
case $res in
…
esac
fi
Edit: you could also do
res=0
my_command || res=$?
case $res in
…
esac
Related videos on Youtube
Paulo Matos
Updated on September 18, 2022Comments
-
Paulo Matos almost 2 years
Take a look at these attempts:
$ case `true` in 0) echo success ;; *) echo fail ;; esac fail $ if `true` ; then > echo "success" > else > echo "fail" > fi success
Now, why is the case statement failing? You might wonder why I don't just use the
if
statement and I shall explain. My command if complex and might return different return codes on which I want act on. I don't want to run the command multiple times and I can't do:my_command res = $? case $? in ... esac
This is because I use
set -e
in my script and therefore ifmy_command
returns failure the script aborts.But I have a workaround...
set +e my_command res=$? set -e case $? in ... esac
But this is ugly, so returning to my initial question... why can I just use the
case my_command in ... esac
version?