I don't have enough reputation to comment, but the accepted answer was missing a closing } on line 5.
After fixing this, the code will throw a -ne: unary operator expected error, which points to a problem: PIPESTATUS is overwritten by the conditional following the if command, so the return value of process_commands will never be checked!
This is because [ ${PIPESTATUS[0]} -ne 0 ] is equivalent to test ${PIPESTATUS[0]} -ne 0, which changes $PIPESTATUS just like any other command. For example:
return0 () { return 0;}
return3 () { return 3;}
return0 | return3
echo "PIPESTATUS: ${PIPESTATUS[@]}"
This returns PIPESTATUS: 0 3 as expected. But what if we introduce conditionals?
return0 | return3
if [ ${PIPESTATUS[0]} -ne 0 ]; then
echo "1st command error: ${PIPESTATUS[0]}"
elif [ ${PIPESTATUS[1]} -ne 0 ]; then
echo "2nd command error: ${PIPESTATUS[1]}"
else
echo "PIPESTATUS: ${PIPESTATUS[@]}"
echo "Both return codes = 0."
fi
We get the [: -ne: unary operator expected error, and this:
PIPESTATUS: 2
Both return codes = 0.
To fix this, $PIPESTATUS should be stored in a different array variable, like so:
return0 | return3
TEMP=("${PIPESTATUS[@]}")
echo "TEMP: ${TEMP[@]}"
if [ ${TEMP[0]} -ne 0 ]; then
echo "1st command error: ${TEMP[0]}"
elif [ ${TEMP[1]} -ne 0 ]; then
echo "2nd command error: ${TEMP[1]}"
else
echo "TEMP: ${TEMP[@]}"
echo "All return codes = 0."
fi
Which prints:
TEMP: 0 3
2nd command error: 3
as intended.
Edit: I fixed the accepted answer, but I'm leaving this explanation for posterity.