Re: [Help-bash] difference of $? and ${PIPESTATUS[0]}
On 4/22/24 2:13 AM, felix wrote: I could explain that '$?' is result of bash's if...then...fi group command executed correctly and PIPESTATUS hold result of "most-recently-executed foreground pipeline", but man page say: PIPESTATUS An array variable (see Arrays below) containing a list of exit status values from the processes in the most-recently-executed foreground pipeline (which may contain only a single command). ? Expands to the exit status of the most recently executed fore‐ ground pipeline. It's clumsy wording, no doubt, but the two aren't intended to be the same or necessarily have the same value. The language in the description of $? is very close to POSIX, since the POSIX grammar basically makes any command a pipeline. It's formal so the standard can relate it to the grammar, but very few people think of if a; then echo b; else echo c; fi as a `pipeline'. If so, "$?" have to be equivalent to "${PIPESTATUS[0]}", I think. No, even if this were true, it would be the last member of PIPESTATUS, modulo the `pipefail' setting. I suggest that man page should be modified to replace "foreground pipeline" by "command" under "?" paragraph. Yeah, that's probably closer to the real meaning. The description of PIPESTATUS refers to pipelines as described in Pipelines under SHELL GRAMMAR (which can also be a Simple Command from the same section). -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/ OpenPGP_signature.asc Description: OpenPGP digital signature
Re: [Help-bash] difference of $? and ${PIPESTATUS[0]}
On Mon, 22 Apr 2024, at 8:56 AM, Oğuz wrote: > On Mon, Apr 22, 2024 at 10:24 AM Kerin Millar wrote: >> I cannot find anything in the manual that concretely explains why bash >> behaves as it does in this instance. > > Me neither, but the current behavior is useful. Take `while false | Very much so. The clarity of the documentation is my only concern. -- Kerin Millar
Re: [Help-bash] difference of $? and ${PIPESTATUS[0]}
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> 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 $?.
Re: [Help-bash] difference of $? and ${PIPESTATUS[0]}
On Mon, 22 Apr 2024, 18:13 felix, wrote: > Hi, > > Coming on this very old thread: > > [the] man page say[s]: > > PIPESTATUS > An array variable (see Arrays below) containing a list of exit > status values from the processes in the most-recently-executed > foreground pipeline (which may contain only a single command). > > ? Expands to the exit status of the most recently executed fore‐ > ground pipeline. > > If so, "$?" have to be equivalent to "${PIPESTATUS[0]}", I think. > > I suggest that man page should be modified to replace "foreground pipeline" > by "command" under "?" paragraph. Ironically the description of ? is correct, subject to understanding shopt -u lastpipe, but the description of LASTPIPE is incongruent with the meanings of "pipeline", and that the status of a compound command is the status of its last inner command not counting any command whose status is checked by the compound command itself (so commands immediately followed by ";do", ";then", or ";else" do not contribute to the status of the compound command). On the other hand, LASTPIPE is set after a simple command, ignoring any '!' or 'time' prefix, or any (explicit or implicit) subshell because a subshell's exit status is reported via exit+wait in the same manner as a simple command). That in turn implies that it will be set after any non-trivial pipeline, because that forces each of its parts to be executed as a subshell. -Martin
Re: [Help-bash] difference of $? and ${PIPESTATUS[0]}
Le Mon, Apr 22, 2024 at 10:56:03AM +0300, Oğuz a écrit : > > Me neither, but the current behavior is useful. I agree! Anyway, reading man page, `$?` have to be equivalent to `${PIPESTATUS[-1]}`! which is not always the case. > I've never seen anything like that in a real shell script. I have to confess my neither, upto this post on SO, more than ten years later! -- Félix Hauri -- http://www.f-hauri.ch
Re: [Help-bash] difference of $? and ${PIPESTATUS[0]}
On Mon, Apr 22, 2024 at 10:24 AM Kerin Millar wrote: > I cannot find anything in the manual that concretely explains why bash > behaves as it does in this instance. Me neither, but the current behavior is useful. Take `while false | false; do :; done' for example, if bash reported the status of the while command in PIPESTATUS you couldn't tell which part of your condition failed. This isn't reliable when the lastpipe shell option is in effect and you have `some command | break' in your loop body but I've never seen anything like that in a real shell script.
Re: [Help-bash] difference of $? and ${PIPESTATUS[0]}
On Mon, Apr 22, 2024 at 09:15:52AM +0200, felix wrote: > Le Mon, Apr 22, 2024 at 07:44:48AM +0100, Kerin Millar a écrit : > > On Mon, 22 Apr 2024, at 7:13 AM, felix wrote: > > > ... > > > 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 !! > > > ... > > > If so, "$?" have to be equivalent to "${PIPESTATUS[0]}", I think. > > > > No. That would only be true in the event that the pipeline comprises a > > single command. The present documentation is correct. > > I was wrong: the last is `${PIPESTATUS[-1]}' -> '${PIPESTATUS[3]}' in this > case, > anyway > $PIPESTATUS[3]=>4 and $?=>0 !! > > > It's worth reading the section of the manual that concerns "Pipelines". > Reading this, if I could understand why > false;echo ${PIPESTATUS[0]} $? > 1 1 > I'm still don't be able to explain this: > if false;then echo Don't print that's;fi; echo ${PIPESTATUS[0]} $? > 1 0 > > -- > Félix Hauri -- http://www.f-hauri.ch The exit status of an "if" statement is the exit status of the last command executed within the body of the statement. In your last example, nothing is executed by the body of the "if" statement, so the exit status of the statement is zero. >From the bash manual about this in the "Compound Commands" section: The exit status is the exit status of the last command executed, or zero if no condition tested true. The PIPESTATUS array is set by virtue of executing the "false" command in the "if"-satement's test. -- Andreas (Kusalananda) Kähäri Uppsala, Sweden .
Re: [Help-bash] difference of $? and ${PIPESTATUS[0]}
On Mon, 22 Apr 2024, at 7:44 AM, Kerin Millar wrote: > On Mon, 22 Apr 2024, at 7:13 AM, felix wrote: >> Hi, >> >> Comming on this very old thread: >> >> On Wed, 4 Dec 2013 14:40:11 -0500, Greg Wooledge wrote: >>> >>> The most obvious difference is that $? is shorter. >>> >>> $? is also POSIX standard (older than POSIX in fact), so it works in sh >>> scripts as well. PIPESTATUS is a Bash extension. >>> >>> Finally, note that if you execute a pipeline, $? will contain the exit >>> status of the last command in the pipeline, not the first command, >>> which is what ${PIPESTATUS[0]} would contain. (If you execute a simple >>> command instead of a pipeline, then they would both have the same value.) >> >> Some asked on StackOverflow.com: >> Why does a Bash while loop result in PIPESTATUS "1" instead of "0"? >> https://stackoverflow.com/q/78351657/1765658 >> >> 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 just looked at the the Stack Overflow thread. It's not explained by forking, at least. Here's a simpler test case, using the true and false builtins. $ if false; then true; fi $ echo "$?" "${PIPESTATUS[@]@Q}" 0 '1' Clearly, ? shows the exit status of if, whereas PIPESTATUS shows the exit status of false, which counts as a foreground pipeline in its own right. I presume that this is by design but I must agree that it is surprising. I cannot find anything in the manual that concretely explains why bash behaves as it does in this instance. Here is another case in which the pipeline comprises two compound commands, with the values of $? and PIPESTATUS being exactly as one would expect. $ if false; then true; fi | if true; then false; fi; echo "$?" "${PIPESTATUS[@]@Q}" 1 '0' '1' -- Kerin Millar
Re: [Help-bash] difference of $? and ${PIPESTATUS[0]}
Le Mon, Apr 22, 2024 at 07:44:48AM +0100, Kerin Millar a écrit : > On Mon, 22 Apr 2024, at 7:13 AM, felix wrote: > > ... > > 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 !! > > ... > > If so, "$?" have to be equivalent to "${PIPESTATUS[0]}", I think. > > No. That would only be true in the event that the pipeline comprises a single > command. The present documentation is correct. I was wrong: the last is `${PIPESTATUS[-1]}' -> '${PIPESTATUS[3]}' in this case, anyway $PIPESTATUS[3]=>4 and $?=>0 !! > It's worth reading the section of the manual that concerns "Pipelines". Reading this, if I could understand why false;echo ${PIPESTATUS[0]} $? 1 1 I'm still don't be able to explain this: if false;then echo Don't print that's;fi; echo ${PIPESTATUS[0]} $? 1 0 -- Félix Hauri -- http://www.f-hauri.ch
Re: [Help-bash] difference of $? and ${PIPESTATUS[0]}
On Mon, 22 Apr 2024, at 7:13 AM, felix wrote: > Hi, > > Comming on this very old thread: > > On Wed, 4 Dec 2013 14:40:11 -0500, Greg Wooledge wrote: >> >> The most obvious difference is that $? is shorter. >> >> $? is also POSIX standard (older than POSIX in fact), so it works in sh >> scripts as well. PIPESTATUS is a Bash extension. >> >> Finally, note that if you execute a pipeline, $? will contain the exit >> status of the last command in the pipeline, not the first command, >> which is what ${PIPESTATUS[0]} would contain. (If you execute a simple >> command instead of a pipeline, then they would both have the same value.) > > Some asked on StackOverflow.com: > Why does a Bash while loop result in PIPESTATUS "1" instead of "0"? > https://stackoverflow.com/q/78351657/1765658 > > 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 and PIPESTATUS hold result of "most-recently-executed > foreground pipeline", but man page say: > > PIPESTATUS > An array variable (see Arrays below) containing a list of exit > status values from the processes in the most-recently-executed > foreground pipeline (which may contain only a single command). > > ? Expands to the exit status of the most recently executed fore‐ > ground pipeline. > > If so, "$?" have to be equivalent to "${PIPESTATUS[0]}", I think. No. That would only be true in the event that the pipeline comprises a single command. The present documentation is correct. > > I suggest that man page should be modified to replace "foreground pipeline" > by "command" under "?" paragraph. It's worth reading the section of the manual that concerns "Pipelines". Not least, to concretely understand what they are in grammatical terms, but also to understand that the exit status of a pipeline is "the exit status of the last command, unless the pipefail option is enabled". That is, the last command that constitutes the pipeline; there need not be more than one. -- Kerin Millar
Re: [Help-bash] difference of $? and ${PIPESTATUS[0]}
Hi, Comming on this very old thread: On Wed, 4 Dec 2013 14:40:11 -0500, Greg Wooledge wrote: > > The most obvious difference is that $? is shorter. > > $? is also POSIX standard (older than POSIX in fact), so it works in sh > scripts as well. PIPESTATUS is a Bash extension. > > Finally, note that if you execute a pipeline, $? will contain the exit > status of the last command in the pipeline, not the first command, > which is what ${PIPESTATUS[0]} would contain. (If you execute a simple > command instead of a pipeline, then they would both have the same value.) Some asked on StackOverflow.com: Why does a Bash while loop result in PIPESTATUS "1" instead of "0"? https://stackoverflow.com/q/78351657/1765658 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 and PIPESTATUS hold result of "most-recently-executed foreground pipeline", but man page say: PIPESTATUS An array variable (see Arrays below) containing a list of exit status values from the processes in the most-recently-executed foreground pipeline (which may contain only a single command). ? Expands to the exit status of the most recently executed fore‐ ground pipeline. If so, "$?" have to be equivalent to "${PIPESTATUS[0]}", I think. I suggest that man page should be modified to replace "foreground pipeline" by "command" under "?" paragraph. -- Félix Hauri -- http://www.f-hauri.ch