[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Possible bug in bash
Re: Possible bug in bash
Fri, 13 May 2022 20:16:10 +1200
Thank you very much for the detailed description of this scenario.
Before opening the bug I looked online for if-then-else vs [[ and no proper
information was available, definitely not to the extent you explain here.
This is very useful and rare knowledge and the effort you took to explain this
is highly appreciated.
On Fri, 13 May 2022 12:39:10 +0700 (ICT)
Robert Elz <kre@munnari.OZ.AU> wrote:
> Not a bug.
> Do not use && || as if they were a replacement for if then else fi
> they aren't. In some simple cases it all works out OK, but not in
> general, as you discovered. If you mean if x; then y; else z; fi
> then write that, not x && y || z
> The way and-or lists work, is that the first command (whatever is
> to the left of the first && or || at the the current nesting
> level ... that is any that occur nested inside some other construct
> are not yet seen, but will eventually be used following these
> same rules, if that other construct is evaluated) is executed.
> To this point it is just like an if statement, in that the list
> between the "if" and the corresponding "then" is evaluated.
> Then, forever (until the entire and-or list is consumed, there
> can be many && and || operators, in any order) when the
> operator is reached, if the current exit status is 0, then
> if the operator is && we execute the next command in the and-or
> list, the exit status changes to the result of that command.
> If the operator was || then simply skip to the next && or ||
> operator in this and-or list, the exit status does not change,
> and continue.
> If, when one of those operators is reached the current exit status
> is non-zero, we do just the samd, but in reverse, execute the next
> command (updating the exit status as that happens) if the operator
> is || and skip it leaving the exit status unchanged, if &&
> So, in your x && y || z command, x (the [[ command) is executed,
> exit status is 0 (true) the && is reached, so we go on and
> execute y (the brace group command in your example). Executing
> a group sets the exit status of the group to the status of
> the last command in the group that was executed. In your example
> the ls command, which in your case was not zero.
> So, when we get to the || operator, the exit status is not
> zero, which means we go on and execute the next command z (echo
> in your example).
> Note particularly that there is no operator precedence between
> && and || - they are the same (unlike in C for example)
> This is completely different from if x ; then y ; else z ; fi
> whers what happens in y (if executed) has no bearing at all
> upon whether z is executed - there exactly one of y or z
> gets executed, never both. Not true of and-or lists.
> The exit status of the whole construct is also different.
> In an and-or list, the exit status of that list is that
> of whichever command (x, y, or z) was executed last. The
> exit status of the if form is that of whatever command in
> the then or else lists (y or z -- cannot be both) was
> executed, or 0 if neither was (that is, if x exited non-zero
> and there was no else part). The actual exit status of
> x is never used as the exit status of the if command.
> So if you mean "if" write "if" not && - using an and-or
> list when an if should have been used does not show you
> as being a "cool power programmer, using advanced syntax
> that the boring newbies do not understand" rather it shows
> that you are an incompetant beginner, trying to master
> concepts not yet understood, and making a mess of it.
> Use the proper construct for what is needed, always.