Compare integer in bash, unary operator expected

The following code gives

[: -ge: unary operator expected

when

i=0

if [ $i -ge 2 ]
then
    #some code
fi

why?


Solution 1:

Your problem arises from the fact that $i has a blank value when your statement fails. Always quote your variables when performing comparisons if there is the slightest chance that one of them may be empty, e.g.:

if [ "$i" -ge 2 ] ; then
  ...
fi

This is because of how the shell treats variables. Assume the original example,

if [ $i -ge 2 ] ; then ...

The first thing that the shell does when executing that particular line of code is substitute the value of $i, just like your favorite editor's search & replace function would. So assume that $i is empty or, even more illustrative, assume that $i is a bunch of spaces! The shell will replace $i as follows:

if [     -ge 2 ] ; then ...

Now that variable substitutions are done, the shell proceeds with the comparison and.... fails because it cannot see anything intelligible to the left of -gt. However, quoting $i:

if [ "$i" -ge 2 ] ; then ...

becomes:

if [ "    " -ge 2 ] ; then ...

The shell now sees the double-quotes, and knows that you are actually comparing four blanks to 2 and will skip the if.

You also have the option of specifying a default value for $i if $i is blank, as follows:

if [ "${i:-0}" -ge 2 ] ; then ...

This will substitute the value 0 instead of $i is $i is undefined. I still maintain the quotes because, again, if $i is a bunch of blanks then it does not count as undefined, it will not be replaced with 0, and you will run into the problem once again.

Please read this when you have the time. The shell is treated like a black box by many, but it operates with very few and very simple rules - once you are aware of what those rules are (one of them being how variables work in the shell, as explained above) the shell will have no more secrets for you.

Solution 2:

Judging from the error message the value of i was the empty string when you executed it, not 0.

Solution 3:

I need to add my 5 cents. I see everybody use [ or [[, but it worth to mention that they are not part of if syntax.

For arithmetic comparisons, use ((...)) instead.

((...)) is an arithmetic command, which returns an exit status of 0 if the expression is nonzero, or 1 if the expression is zero. Also used as a synonym for "let", if side effects (assignments) are needed.

See: ArithmeticExpression