To our delight, pipefail
has been standardized in POSIX and implemented in all POSIX shells. However, PIPESTATUS
(pipestatus
for zsh) is only available in bash and zsh. This project will make PIPESTATUS
available to all POSIX shells.
- Supports
pipefail
behavior - Support for
errexit
shell option - No global variables except
PIPESTS
- All POSIX shells supported
- sh, bash, ksh, zsh, etc.
- Shortest code possible
- Extra: Function to ignore
SIGPIPE
(igpipe
)
Note: The Bourne shell is not supported because it is legacy, not POSIX compliant, and no longer used.
This replaces the old FAQ (How do I get the exit code of cmd1 in cmd1|cmd2) on comp.unix.shell.
Use it as:
# From
cmd1 | cmd2 | cmd3
# To
pipe 'cmd1 | cmd2 | cmd3' "$@"
# or
pipe -fail 'cmd1 | cmd2 | cmd3' "$@"
# exit codes are in
echo "$? and $PIPESTS" # => 0 and 0 0 0
Note: sh-pipestatus separates each command in the pipeline with <whitespace>|<whitespace>
(whitespace: space, tab, newline). Therefore, if part of a command contains this delimiter, it will be misinterpreted. To avoid this, use the following instead or shell functions.
# From
pipe 'echo "foo | bar" | tr a-z A-Z'
# To
pipe 'echo "foo ""| bar" | tr a-z A-Z'
# From
pipe 'echo "foo" | case $1 in x | y) cat ;; esac | tr a-z A-Z' x
# To
pipe 'echo "foo" | case $1 in x|y) cat ;; esac | tr a-z A-Z' x
# From
pipe 'echo $((1 | 2)) | tr 3 C'
# To
pipe 'echo $((1|2)) | tr 3 C'
When you enable pipefail
, you will probably be plagued by SIGPIPE
. The igpipe
function is for ignoring SIGPIPE
.
set -o pipefail
seq 100000 | cat | head >/dev/null
echo $? # => 141
igpipe seq 100000 | igpipe cat | head >/dev/null
echo $? # => 0