254

I have a bash variable depth and I would like to test if it equals 0. In case yes, I want to stop executing of script. So far I have:

zero=0;

if [ $depth -eq $zero ]; then
    echo "false";
    exit;
fi

Unfortunately, this leads to:

 [: -eq: unary operator expected

(might be a bit inaccurate due to translation)

Please, how can I modify my script to get it working?

codeforester
  • 39,467
  • 16
  • 112
  • 140
Perlnika
  • 4,796
  • 8
  • 36
  • 47

6 Answers6

263

Looks like your depth variable is unset. This means that the expression [ $depth -eq $zero ] becomes [ -eq 0 ] after bash substitutes the values of the variables into the expression. The problem here is that the -eq operator is incorrectly used as an operator with only one argument (the zero), but it requires two arguments. That is why you get the unary operator error message.

EDIT: As Doktor J mentioned in his comment to this answer, a safe way to avoid problems with unset variables in checks is to enclose the variables in "". See his comment for the explanation.

if [ "$depth" -eq "0" ]; then
   echo "false";
   exit;
fi

An unset variable used with the [ command appears empty to bash. You can verify this using the below tests which all evaluate to true because xyz is either empty or unset:

  • if [ -z ] ; then echo "true"; else echo "false"; fi
  • xyz=""; if [ -z "$xyz" ] ; then echo "true"; else echo "false"; fi
  • unset xyz; if [ -z "$xyz" ] ; then echo "true"; else echo "false"; fi
cyon
  • 9,340
  • 4
  • 22
  • 26
  • 1
    I am getting depth as a result from another program. I tried to echo it and there was nothing in the output. However, when I use [[]] as @Jacek Dominiak suggested, script works correctly (what is quite strange if variable is really unset). I have to admit that I do not really understand whats going on here... – Perlnika Oct 26 '12 at 11:54
  • 7
    Your depth variable is unset. That means bash sees an expression which says `[ -eq 0 ]; then` which doesn't make sense to it. `[[ ]]` is the safer version which seems to make bash see it as [[ null -eq 0 ]] which is correct. – cyon Oct 26 '12 at 12:05
  • 3
    A safer way to check is to enclose both sides in double quotes, i.e. `if [ "$depth" -eq "0" ]`; this way, an unset variable (`$depth`) evaluates to "" (which of course does not equal zero) – Doktor J Sep 13 '16 at 16:35
  • 1
    @DoktorJ Agreed, that's a better way to do it. I'll update the code. – cyon Sep 14 '16 at 09:38
  • "An unset variable used with the [ command appears empty to bash." that helped me! Thanks – Hasan Rumman Sep 25 '17 at 04:39
  • 2
    This gives me: `[: Illegal number:` error. – Daniel Kmak Jun 20 '18 at 21:52
  • This does not work if the output is a decimal : `[: : integer expression expected` – alper Feb 21 '21 at 15:56
82

Double parenthesis (( ... )) is used for arithmetic operations.

Double square brackets [[ ... ]] can be used to compare and examine numbers (only integers are supported), with the following operators:

· NUM1 -eq NUM2 returns true if NUM1 and NUM2 are numerically equal.

· NUM1 -ne NUM2 returns true if NUM1 and NUM2 are not numerically equal.

· NUM1 -gt NUM2 returns true if NUM1 is greater than NUM2.

· NUM1 -ge NUM2 returns true if NUM1 is greater than or equal to NUM2.

· NUM1 -lt NUM2 returns true if NUM1 is less than NUM2.

· NUM1 -le NUM2 returns true if NUM1 is less than or equal to NUM2.

For example

if [[ $age > 21 ]] # bad, > is a string comparison operator

if [ $age > 21 ] # bad, > is a redirection operator

if [[ $age -gt 21 ]] # okay, but fails if $age is not numeric

if (( $age > 21 )) # best, $ on age is optional
Dennis
  • 56,821
  • 26
  • 143
  • 139
Raviteja Gubba
  • 1,006
  • 6
  • 9
  • 3
    Can you provide some reasoning/evidence why some approaches are good and others bad? – Dennis Mar 09 '13 at 08:58
  • @Dennis: [This](http://tldp.org/LDP/abs/html/comparison-ops.html) seems to verify the statements in the answer (-> the different brackets for string vs. integer comparison) – mozzbozz Dec 23 '15 at 13:01
  • `best, $ on age is optional` It's not working without `$` – Jean-Marc Amon Nov 21 '17 at 17:36
  • 1
    `if (( age > 21 ))` and `if (( $age > 21 ))` is different sometimes. You can see https://github.com/koalaman/shellcheck/wiki/SC2004 – Jess Chen May 15 '21 at 17:31
26

Try:

zero=0;

if [[ $depth -eq $zero ]]; then
  echo "false";
  exit;
fi
Jacek Dominiak
  • 857
  • 1
  • 9
  • 19
25

you can also use this format and use comparison operators like '==' '<='

  if (( $total == 0 )); then
      echo "No results for ${1}"
      return
  fi
Gurubaran
  • 718
  • 8
  • 13
7

Specifically: ((depth)). By example, the following prints 1.

declare -i x=0
((x)) && echo $x

x=1
((x)) && echo $x
Stephen Niedzielski
  • 2,497
  • 1
  • 28
  • 34
3

You can try this:

: ${depth?"Error Message"} ## when your depth variable is not even declared or is unset.

NOTE: Here it's just ? after depth.

or

: ${depth:?"Error Message"} ## when your depth variable is declared but is null like: "depth=". 

NOTE: Here it's :? after depth.

Here if the variable depth is found null it will print the error message and then exit.

BuZZ-dEE
  • 6,075
  • 12
  • 66
  • 96
Prabhat Kumar Singh
  • 1,711
  • 15
  • 20