bash vs zsh – Why `==` Behaves Differently Inside `[ … ]`

bashtestzsh

I get what I expected when doing this in bash:

[ "a" == "a" ] && echo yes

It gave me yes.

But when I do this in zsh, I get the following:

zsh: = not found

Why does the same command (/usr/bin/[) behave differently in different shells?

Best Answer

It's not /usr/bin/[ in either of the shells. In Bash, you're using the built-in test/[ command, and similarly in zsh.

The difference is that zsh also has an = expansion: =foo expands to the path to the foo executable. That means == is treated as trying to find a command called = in your PATH. Since that command doesn't exist, you get the error

zsh: = not found

that you saw (and in fact, this same thing would happen even if you actually were using /usr/bin/[).


You can use == here if you really want. This works as you expected in zsh:

[ "a" "==" "a" ] && echo yes

because the quoting prevents =word expansion running. You could also disable the equals option with setopt noequals.


However, you'd be better off either:

  • Using single =, the POSIX-compatible equality test; or
  • Better still, using the [[ conditionals with == in both Bash and zsh. In general, [[ is just better and safer all around, including avoiding this kind of issue (and others) by having special parsing rules inside.