On Mon, Apr 22, 2024 at 08:13:16AM +0200, felix wrote: > Then after some tests: > > if ls /wrong/path | wc | cat - /wrong/path | sed 'w/wrong/path' >/dev/null > ; then > echo Don't print this' > fi ; echo ${?@Q} ${PIPESTATUS[@]@A} $(( $? ${PIPESTATUS[@]/#/+} )) > > ls: cannot access '/wrong/path': No such file or directory > cat: /wrong/path: No such file or directory > sed: couldn't open file /wrong/path: No such file or directory > '0' declare -a PIPESTATUS=([0]="2" [1]="0" [2]="1" [3]="4") 7 > > Where $PIPESTATUS[0]=>2 and $?=>0 !! > > I could explain that '$?' is result of bash's if...then...fi group command > executed correctly [...]
That is indeed the issue here. $? contains the exit status of the "if" command, not of the pipeline. hobbit:~$ help if [...] The exit status of the entire construct is the exit status of the last command executed, or zero if no condition tested true. [...] hobbit:~$ if (exit 42); then :; fi hobbit:~$ echo $? 0 If you remove the 'if' from your example, you get a very different result: hobbit:~$ /wrong/path | wc | cat - /wrong/path | sed 'w/wrong/path' >/dev/null bash: /wrong/path: No such file or directory sed: couldn't open file /wrong/path: No such file or directory hobbit:~$ echo "<$?> <${PIPESTATUS[@]@A}>" <4> <declare -a PIPESTATUS=([0]="127" [1]="0" [2]="141" [3]="4")> Here, $? is the exit status of the last command in the pipeline, as it should be. I don't know where your notion that $? and PIPESTATUS[0] should be equivalent came from, but it is never right, except in the case where the "pipeline" is just a single command. Introducing the 'if' separates the value of $? and the values of the PIPESTATUS array entirely. They no longer refer to the same pipeline at all. $? contains the exit status of 'if' itself, and PIPESTATUS contains the exit statuses of the commands from the pipeline. If you want $? to contain the exit status of the pipeline instead, you need to reference it from within the 'if' statement. hobbit:~$ if (exit 42); then echo "yes $?"; else echo "no $?"; fi no 42 Once the 'if' terminates, the exit status of the pipeline is no longer reliably available through $?.