106

Here my problem is to find the difference of using single bracket [ ] and double brackets [[ ]] in if statement.

#!/bin/bash
vara=08;
varb=10;

## single bracket in if statment is working.
if [ $vara -lt $varb ]; then
echo "yes";
else
echo "no";
fi


## double brackets in if statment is not working; throwing an error like below.
## [[: 08: value too great for base (error token is "08")
if [[ $vara -lt $varb ]]; then
echo "yes";
else
echo "no";
fi
codeforester
  • 39,467
  • 16
  • 112
  • 140
Thaangaraj
  • 1,100
  • 2
  • 7
  • 10

1 Answers1

177

The shell tries to interpret 08 as an octal number, as it starts with a zero. Only digits 0-7 are, however, allowed in octal, as decimal 8 is octal 010. Hence 08 is not a valid number, and that's the reason for the error.

Single brackets are kind of "compatibility mode" with sh, and sh does not know about octal numbers.

So, if you use single square brackets, "010" will be interpreted as 10, while with double square brackets, "010" will be interpreted as 8.

If you use single square brackets, "08" will be interpreted as 8, while with double square brackets, it is not a valid number and leads to an error.

You can avoid the error by using the solution described here: https://stackoverflow.com/a/12821845/1419315

if [[ ${vara#0} -lt ${varb#0} ]]

or

if [[ $((10#$vara)) -lt $((10#$varb)) ]]
Community
  • 1
  • 1
JohnB
  • 13,315
  • 4
  • 38
  • 65
  • 12
    The problem is the leading 0, which will cause the shell to interpret the string as octal. Try this http://stackoverflow.com/a/12821845/1419315 solution: `if [[ ${vara#0} -lt ${varb#0} ]]` – JohnB Jul 16 '14 at 10:04
  • 26
    You can explicitly specify the number base with _n#_, so `10#08` will be recognised. – rojomoke Jul 16 '14 at 10:05
  • 4
    Thank you! This also appears to work within any arithmetic expression, ex. `$(( 10#$vara - 8 ))` – Eliot Jun 23 '17 at 17:24
  • 3
    This works too: VariableWithLeadingZero=$(echo $VariableWithLeadingZero | sed 's/^0*//') – CMP Sep 08 '20 at 08:05
  • 2
    `[[ ${vara#0} -lt ${varb#0} ]]` breaks for numbers with more than one leading zero (e.g. `008`). `[[ 10#$vara -lt 10#$varb ]]` or `(( 10#$vara < 10#$varb ))` works with such numbers. – pjh Feb 20 '22 at 01:57