Command Pipeline Errors

When chaining commands in Bash using the pipe | separator, the commands execute in sequence, with the output of the first command being used as the input to the second command.

When running a single Bash command, it is possible to detect if an error has occurred by examining the $? built-in Bash variable directly after the command has completed. A zero 0 return value means success, a non-zero return value means that an error has occurred.

For example, trying to write output to a new file in the root of the file system.

$ echo "Create a file with one line in it" > /new-file.txt
-bash: /new-file.txt: Permission denied
$ echo $?
1

Whereas writing a file to your home path will succeed as expected.

$ echo "Create a file with one line in it" > ~/new-file.txt
$ echo $?
0

But what happens if an error occurs when executing a command within a piped list of commands? In this case, the default is for the last command to set the return value for the entire command chain.

$ cat /new-file.txt | wc
cat: /new-file.txt: No such file or directory
       0       0       0
$ echo $?
0

Which doesn’t help very much if you are trying to detect when anything has gone wrong within the combined command. This can be overridden by setting the pipefail Bash option.

$ set -o pipefail
$ cat /new-file.txt | wc
cat: /new-file.txt: No such file or directory
       0       0       0 
$ echo $?
1

This can be extremely useful if you regularly chain commands together, as the return value can be used to display a message to the user indicating an issue has occurred within the command chain.