With bash
and a few other shells, you can use the pipefail
option, which when enabled causes the exit status of a pipeline to be that of the rightmost component that failed as opposed to the rightmost component:
(set -o pipefail; cmd | sed 's/^/ | /') || exit
Another option is to redirect stdout to a process substitution instead of using a pipe:
cmd > >(sed 's/^/ | /') || exit
Though beware that sed
which in that case is started in background and is not waited for, may not have finished writing by the time the next command is run.
Specific to bash
, there's the $PIPESTATUS
special array (zsh has a $pipestatus
equivalent) which records the exit status of every component in a pipeline:
cmd | sed 's/^/ | /'; ret=${PIPESTATUS[0]}
[ "$ret" -eq 0 ] || exit "$ret"
POSIXly, you can do:
{
ret=$(
exec 4>&1
{
cmd 3>&- 4>&-
echo "$?" >&4
} | sed 's/^/ | /' >&3 3>&- 4>&-
)
} 3>&1
[ "$ret" -eq 0 ] || exit "$ret"
You could use a helper function:
prefix() (
prefix=$1; shift
exit "$(
exec 4>&1
{
"$@" 3>&- 4>&-
echo "$?" >&4 3>&- 4>&-
} | PREFIX=$prefix awk '{print ENVIRON["PREFIX"] $0}' >&3 3>&- 4>&-
)"
) 3>&1
prefix ' | ' cmd
(here switching to awk
so as to be able to use arbitrary prefixes.
&&
sed||
rm (but this won't work for exit 1) – alecxs Jun 11 '20 at 07:38ret=${PIPESTATUS[0]}
is perfectly complete and obviates the need for a temp file altogether, but I'll just add that if you do use a temp file, the better way to remove it is via atrap
, e.g.,trap
rm -f "$tmpfile"EXIT
https://unix.stackexchange.com/questions/480330/temporary-folder-that-automatically-destroyed-after-process-exit – michael Jun 11 '20 at 08:17