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.