How do I check if command failed... with a pipe?
So I have a script like this:
somecommad | grep --invert-match something
I'd like to be able to conditionally run a different command if somecommand
fails. Here's what I tried:
somecommand | grep --invert-match something || {
echo 'Oops'
}
But that didn't work (the grep
wasn't executed). What is the proper way to do this?
Solution 1:
@steeldriver mentioned in the comments that PIPESTATUS
might work. I tried it, and it worked well. Here's what I did:
somecommand | grep --invert-match something
if [ "${PIPESTATUS[0]}" != "0" ]; then
echo 'Oops'
fi
It runs the command as before, but then I have an if
statement to look at the PIPESTATUS
array. I only care about the first element, so that is the one I look at. I check it it failed (if the exit code is not 0
), and it it did fail, run echo 'Oops'
Solution 2:
Another way, depending on the exact behaviour needed, is to use the pipefail
option:
The exit status of a pipeline is the exit status of the last command in the pipeline, unless the
pipefail
option is enabled (see The Set Builtin). Ifpipefail
is enabled, the pipeline's return status is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands exit successfully.
So, if you don't care which of somecommand
or grep
failed, as long as one of those did fail:
set -o pipefail
if ! somecommand | grep --invert-match something; then
echo 'Oops'
fi