bug-bash
[Top][All Lists]
Advanced

[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 $?.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]