Bash Scripting – How to Get Both PIPESTATUS and Output in Bash Script

bashpipe

I'm trying to get last modification date of a file with this command

TM_LOCAL=`ls -l --time-style=long-iso ~/.vimrc | awk '{ print $6" "$7 }'`

TM_LOCAL has value like "2012-05-16 23:18" after execution of this line

I'd also like to check PIPESTATUS to see if there was an error. For example if file does not exists, ls returns 2. But $? has value 0 as it has the return value of awk.

If I run this command alone, I can check the return value of ls by looking at ${PIPESTATUS[0]}

ls -l --time-style=long-iso ~/.vimrc | awk '{ print $6" "$7 }'

But $PIPESTATUS does not work as I've expected if I assign the output to a variable as in the first example. In this case, $PIPESTATUS array has only 1 element which is same as $?

So, the question is, how can I get both $PIPESTATUS and assign the output to a variable at the same time?

Best Answer

You could do this:

TM_LOCAL=$(ls -l --time-style=long-iso ~/.vimrc | \
             awk '{ print $6" "$7 }' ; exit ${PIPESTATUS[0]} )

Then $? will be the return code from ls. This doesn't work if you need the return code from more than one of the pipe parts (but you could split the pipeline if the output isn't too large, as it is here).

Here's a rather expensive way of getting the full PIPESTATUS array and the output. Not very elegant, but haven't found anything else:

result=$(echo -e "a\nb\nc" | \
          ( cat ; exit 1 ) | \
          ( cat ; exit 42 ) ; echo ${PIPESTATUS[@]})
output=$(head -n -1 <<< "$result")
status=($(tail -n 1 <<< "$result"))
echo "Output:"
echo "$output"
echo "Results:"
echo "${status[@]}"

Which gives:

Output:
a
b
c
Results:
0 1 42
Related Question