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. kre