Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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?

share|improve this question
up vote 5 down vote accepted

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:

0 1 42
share|improve this answer
This work in my case, but I'm still curious about if there is a way to get complete pipestatus array and the output. – Mustafa Serdar Şanlı May 18 '12 at 13:32

Use set -o pipefail in bash to get the right-most non-zero exit code in a piped command sequence as $?. From man bash:

If set, the return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands in the pipeline exit successfully. This option is disabled by default.

Then you can simply access $?. Use set +o pipefail to disable again.

share|improve this answer

I assume the issue here is that PIPESTATUS goes away in its entirety as soon as you execute a command. You can get the complete PIPESTATUS array in bash version 2 or above this way:

declare -a status

Then access ${status[0]}, ${status[1]}, etc.

share|improve this answer

One option is to check for the existence of your file before getting its modification time with a call to stat. Since stat returns slightly more than you want in the timestamp, you can trim it using parameter expansion

[[ -f ~/.vimrc ]] && TM_LOCAL=$(stat -c '&y' ~/.vimrc 2>/dev/null)
TM_LOCAL=${TM_LOCAL%:*}  # Safe to do, even if stat fails
share|improve this answer

I wanted to send email fron cron only if the exit status was not zero

The trick is that to get the stdin for the end of the pipeline you need to to put it in a subshell - but that seems to hide the PIPESTATUS value ...

test cron spits out some output and exits with 1 or 0 ..

./testcron | (test ${PIPESTATUS[0]} -ne 0 || mail -s "testcron output" paul)

UPDATE: the PIPESTATUS is not visible until the pipeline command is processes

share|improve this answer

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .