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



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

Running it:

$ ./script.sh
./script.sh:3: = not found

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

$ [[ one == one ]] && echo "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"
    echo "not root"
|improve this answer|||||

=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
$ echo ==
zsh: = not found
$ install -m 755 /dev/null ~/bin/=
$ echo ==

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

([[ = ]], [[ == ]] 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.

|improve this answer|||||
  • If the code is supposed to check whether the current user is root or not, it would additionally be better to do that using the id utility. – Kusalananda Feb 21 '19 at 13:32
  • @Kusalananda, in zsh, you'd rather use $USERNAME or $LOGNAME (or better ((EUID == 0)) if it's a check for sufficient privileges) – Stéphane Chazelas Feb 21 '19 at 13:33
  • Those are reset when entering a script? (LOGNAME doesn't seem to be, but USERNAME is). – Kusalananda Feb 21 '19 at 13:34
  • 1
    @Kusalananda, yes, they're mapped to the process attributes, you can also modify them to change euid/uid... – Stéphane Chazelas Feb 21 '19 at 13:35

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'
|improve this answer|||||
  • 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.