[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Help-bash] difference of $? and ${PIPESTATUS[0]}
From: |
Greg Wooledge |
Subject: |
Re: [Help-bash] difference of $? and ${PIPESTATUS[0]} |
Date: |
Mon, 22 Apr 2024 07:22:10 -0400 |
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 $?.