Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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
add comment

4 Answers

up vote 4 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:

Output:
a
b
c
Results:
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
add comment

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
add comment

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
add comment

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
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.