Score:5

How do I check if command failed... with a pipe?

cn flag

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?

hr flag
Perhaps you can use bash's `PIPESTATUS` array: see for example [Get exit status of process that's piped to another](https://unix.stackexchange.com/a/14276/65304)
be flag
When you use a pipe, `grep` starts *before* you can necessarily know if `somecommand` has failed or not. Do you want to the other command's output to go to `grep` as well? `{ somecommand || { echo Oops; }; } | grep ...`.
Score:10
cn flag

@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'

in flag
Does this work regardless of `set -o pipefail`?
cocomac avatar
cn flag
@PedroA I don't know what that does. If you try it, feel free to edit my answer or post your own, though.
eckes avatar
cn flag
Yes it works with pipefail, but not with `set -e -o pipefail` as it won’t reach the if.
Score:7
us flag

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). If pipefail 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
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.