limp_chimp
limp_chimp

Reputation: 15203

Get exit code when piping into grep -v

I have a script like this:

#!/bin/sh

echo "hello"
echo "goodbye"
exit 1

When I run it on its own, I get the failed exit code as I expect.

$ ./fail.sh
hello
goodbye
$ echo $?
1

However, when I run it through grep -v, the exit status changes to success:

$ ./fail.sh | grep -v hello
goodbye
$ echo $?
0

Is there a way to pipe a command's output into grep -v and still have the status code be properly propagated? Of course in the real world the point of this would be to filter the output of a noisy command, while still detecting if the command failed.

Upvotes: 8

Views: 7016

Answers (2)

John Mark Mitchell
John Mark Mitchell

Reputation: 4832

Bash provides an extension set -o pipefail. The following should work:

( set -o pipefail; ./fail.sh | grep -v hello )

You can then test the value in $?:

( set -o pipefail; ./fail.sh | grep -v hello ); if [[ "$?" -eq "1" ]]; then echo success; else echo bummer; fi 

It should output:

goodbye
success

What is happening and why does this work?

As noted in the OP, pipelines normally only return a failure (non-zero return code) if the last command errors. Using set -o pipefail causes a pipeline of commands to produce a failure return code if any command in the pipeline errors. The failure return code that the pipeline passes is the return code of the last failed command.

You can test this by updating your script to:

#!/bin/sh

echo "hello"
echo "goodbye"
exit 5

then run the following:

( set -o pipefail; ./fail.sh | grep -v hello ); echo $?

It should output:

goodbye
5

The above illustrates that set -o pipefail is not just exiting with a non-zero return code but that it is relaying the last non-zero return code verbatim.

Upvotes: 11

hek2mgl
hek2mgl

Reputation: 158170

bash will basically just give you the exit code of the last process in the pipe but you can use the bash specific $PIPESTATUS variable:

./fail.sh | grep -v hello
if [ ! "${PIPESTATUS[0]}" ] ; then
    echo "command has failed"
fi

Upvotes: 5

Related Questions