Wednesday, November 28, 2007

Pipe redirection screwing up exit status?

Have you ever been in a situation where you wanted to filter the output of something in bash. A first guess attempt might look something like this:

./some_command | sed "s/foo/bar/"

However, this has a significant limitation. If you were interested in the exit status, you would only get the exit status of the last command (the sed command in this case)

./some_command | sed "s/foo/bar/"
echo $? # returns exit status of sed

I learned this the hard way doing some scripting last year for a customer where I wanted to pass the output through /usr/bin/tee to log it to a file as it ran. All of a sudden everything started "working", in that all commands returned zero because I was actually getting the return code for /usr/bin/tee.

It turns up in Bash 3.0 and higher, they added an option called "pipestatus", which gives you the exit status of the first command to exit non-zero. Very helpful.

set -o pipestatus
./some_command | sed "s/foo/bar/"
echo $? # returns exit status of ./some_command

Unfortunately, it's not portable beyond bash and ksh93.