3

Been getting errors on my scripts when using this operator. I've some online documentation and double equals should supposedly work. Any ideas?

Zsh reference guide: http://zsh.sourceforge.net/Doc/Release/Conditional-Expressions.html

Script:

#!/bin/zsh

if [ $_user == "root" ]; then
    echo "root"
else
    echo "not root"
fi

Running it:

$ ./script.sh
./script.sh:3: = not found
Kusalananda
  • 333,661
mrjayviper
  • 2,051

3 Answers3

6

Simple answer: a == is a logical operator only inside [[ … ]] constructs.

$ [[ one == one ]] && echo "yes"
yes

And it works also in ksh and bash.

When used outside a [[ … ]] construct a =cmd becomes a filename expansion operator but only in zsh

$ echo ==
zsh: = not found

That is what happens inside the simpler [ … ] construct you used.

But the correct way to test that the user running the shell script is root is to do:

if (( EUID == 0 )); then
    echo "root"
else
    echo "not root"
fi
5

=cmd is a filename expansion operator in zsh that expands to the path of the cmd (resolved by a lookup of $PATH). If no such command is found, that results in a fatal error like when globs don't match.

So == here in an argument of that [ command is asking the shell to lookup the = command in $PATH and zsh is telling you there's no such = anywhere in there.

$ echo =ls
/bin/ls
$ echo ==
zsh: = not found
$ install -m 755 /dev/null ~/bin/=
$ echo ==
/home/stephane/bin/=

Here, either use the standard syntax for the [ command:

[ "$_user" = root ]

Or quote the =:

[ "$_user" '==' root ]

You'd need the quotes for regex matching as well:

[ "$_user" '=~' '^ro+t$' ]

In any case, you'd want to quote $_user or you'd get some confusing error when $_user is empty or unset (and worse including an arbitrary command injection vulnerability in Korn-like shells other than zsh (like bash)).

You can also disable that feature by disabling the equals option (set +o equals) which is not very useful in scripts.

Or use the ksh-style [[...]] construct:

[[ $_user = root ]]
[[ $_user == root ]]
[[ $_user =~ '^ro+t$' ]]

Or a case construct:

case $_user in
  (root) ...
esac

([[ = ]], [[ == ]] and case do pattern matching (wildcard, not regexp))

Note those are conditional expression, there's no need to disambiguate between an assignment and equality operator, so no need for a == operator.

2

A shorter answer at a tangent ..perhaps you read a sample created for running under another shell type?

$ zsh -c 'if [ "x" == "x" ]; then echo "equal!"; fi'
zsh:1: = not found

$ bash -c 'if [ "x" == "x" ]; then echo "equal!"; fi'
equal!
elbeardmorez
  • 121
  • 3
  • OP added the zsh reference guide info after the fact. However, the example might be relevant for others so leaving. – elbeardmorez Feb 21 '19 at 14:34