Search code examples
bashshellnegationexitstatuspipestatus

PIPESTATUS ignores negation?


I just found the following results in bash (version 4.2.25(1)-release):

$ true; echo "${PIPESTATUS[@]}"
0
$ ! true; echo "${PIPESTATUS[@]}"
0
$ false; echo "${PIPESTATUS[@]}"
1
$ ! false; echo "${PIPESTATUS[@]}"
1
$ true && false; echo "${PIPESTATUS[@]}"
1
$ true && ! false; echo "${PIPESTATUS[@]}"
1

So, $PIPESTATUS seems to ignore negations in all cases. Is this a known issue? I couldn't find anything about it. Or is this a wanted behavior? If so, what's the reasoning behind it?

When using a subshell, everything works as I would have expected it:

$ (true && ! false); echo "${PIPESTATUS[@]}"
0

Solution

  • ! a | b | c is interpreted as !{a | b | c;} by the shell & not as {! a;} | b | c.

    Individual command exit statuses are stored in ${PIPESTATUS[@]}.

    The $? refers to exit-status of the entire command, including !.

    You can force (! a) | b | c by actually spawning the subshell. e.g.

    $ true; echo "${PIPESTATUS[@]}"
    0
    $ (! true); echo "${PIPESTATUS[@]}"
    1
    $ false; echo "${PIPESTATUS[@]}"
    1
    $ (! false); echo "${PIPESTATUS[@]}"
    0