I want to execute a command (say ls
) and sed
its output, then save the stdout to a variable, like this,
OUT=$(ls | sed -n -e 's/regexp/replacement/p')
After this, if I try to access the $PIPESTATUS
array, I get only 0
(which is same as $?
). So, how can I get both $PIPESTATUS
as well as capture the entire piped command's stdout?
Note:
ls | sed -n -e 's/regexp/replacement/p'
), I get expected exit statuses in $PIPESTATUS
(like 0 0
)OUT=$(ls)
), I get expected single exit status in $PIPESTATUS
(which is same as $?
)P.S. I know, I could run the command 2 times (first to capture the stdout, second to access $PIPESTATUS
without using Command Substitution), but is there a way to get both in single execution?
You can:
Use a temporary file to pass PIPESTATUS.
tmp=$(mktemp)
out=$(pipeline; echo "${PIPESTATUS[@]}" > "$tmp")
PIPESTATUS=($(<"$tmp")) # Note: PIPESTATUS is overwritten each command...
rm "$tmp"
Use a temporary file to pass out
.
tmp=$(mktemp)
pipeline > "$tmp"
out=$(<"$tmp"))
rm "$tmp"
Interleave output with pipestatus. For example reserve the part from last newline character till the end for PIPESTATUS. To preserve original return status I think some temporary variables are needed:
out=$(pipeline; tmp=("${PIPESTATUS[@]}") ret=$?; echo $'\n' "${tmp[@]}"; exit "$ret"))
pipestatus=(${out##*$'\n'})
out="${out%$'\n'*}"
out="${out%%$'\n'}" # remove trailing newlines like command substitution does
tested with:
out=$(false | true | false | echo 123; echo $'\n' "${PIPESTATUS[@]}");
pipestatus=(${out##*$'\n'});
out="${out%$'\n'*}"; out="${out%%$'\n'}";
echo out="$out" PIPESTATUS="${pipestatus[@]}"
# out=123 PIPESTATUS=1 0 1 0
Notes: