5

I was demonstrating a piece of funny code (or so I think) to my students in class, and to my surprise, it did not work in zsh. I then switched to bash and it worked as expected.

The code is the following:

[ $(( $RANDOM % 6 )) == 0 ] && echo "Boom" || echo "Click"

In bash it prints Boom or Click randomly, as expected. But in zsh I get the error message below:

zsh: = not found

Can anyone explain what is the difference? To my understanding, both shells should interpret scripts in an equivalent manner.

Thanks.

3
  • Since it's an integer comparison, wouldn't it be better practice to use -eq anyhow? Or perhaps use the arithmetic expression directly i.e. (( $RANDOM % 6 == 0 )) && echo "Boom" || echo "Click" Commented Jan 13, 2020 at 18:36
  • @steeldriver And, since it is an aritmetic expression, the $ before the variable name could (should?) be removed. And, since in C the result of an arithmetic expression is a valid result which (if 0) will generate an exit code of 1 (0 otherwise). Then: ((RANDOM%6)) && echo Click || echo Boom should be plenty.
    – user232326
    Commented Jan 13, 2020 at 18:50
  • 2
    Same question on the zsh mailing list a few days ago: zsh.org/mla/users/2020/msg00060.html. See my answer there. Commented Jan 14, 2020 at 7:34

1 Answer 1

7

Try doing unsetopt equals and try again. Or put quotes on the first equals character.

If you use [ for conditions, all arguments are evaluated normally and = at the start of a word is a useful zsh shorthand to get the location of a command. e.g. =ls expands to /bin/ls. Given == zsh looks for an = command and doesn't find one.

Zsh in posix mode (sh emulation) will be a lot more compatible with bash. Many things are compatible and most learnt knowledge of bash is still useful but there are certain things to be aware of if you want to write portable scripts.

Unlike [ which is a builtin, [[ is a reserved word understood by the parser and will give you fewer issues. However in this case you're using arithmetic mode so you simplify it:

    (( RANDOM % 6 == 0 )) && echo "Boom" || echo "Click"

In fact the comparison to zero is even superfluous because, the default return status reflects whether the value is zero, though the sense is reversed:

    (( RANDOM % 6 )) && echo "Click" || echo "Boom"
7
  • So, the expansion of an unquoted argument that starts with an = is a zedshism. And, to be avoided it needs to be quoted. There goes away the concept of (by default) avoiding quotes in zsh.
    – user232326
    Commented Jan 13, 2020 at 21:59
  • You may want to give credit to the user who said all about arithmetic in your post in a comment.
    – user232326
    Commented Jan 13, 2020 at 22:01
  • 1
    Also note that the standard equality comparison operator for the [ utility is =, not ==. Also, in bash (and other POSIX shells but not zsh even in sh emulation), arithmetic expansion undergoes word splitting, so should be quoted like all other word expansions. So for code compatible to zsh, bash and other POSIX shells, that should rather be [ "$(( RANDOM % 6 ))" = 0 ]. = (and == where available) is for string comparison. For integer comparison, it's -eq. Note that $RANDOM is not POSIX, it's a kshism supported by bash and zsh as well. Commented Jan 14, 2020 at 7:23
  • 1
    @Isaac, all shell special characters need to be quoted when you want to pass them literally. That goes for a leading = but also for *, <, |, space, etc. A standalone = like a standalone [ above don't need to be quoted as a special case (like a standalone ! in both bash and zsh). The thing zsh fixed compared to other shells is that unquoted word expansions don't undergo split+glob so do not always need to be quoted (cmdsubst still undergoes split and all word expansions undergo empty removal). (having said that, I agree that =cmd, though a useful feature, is a poor API) Commented Jan 14, 2020 at 7:27
  • @StéphaneChazelas (1) You must (at the very minimum) agree that even the shortest of the quoted operator requires that the fingers press an additional key. A == is never equal to a \==. (2) You may try to convince my fingers that they are equivalent and that they represent the same idea but I am sure that you will fail to convince them. (Cont.)...
    – user232326
    Commented Jan 14, 2020 at 19:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .