AnAwesomeMiner
AnAwesomeMiner

Reputation: 143

'If' command not outputting correct answer

I'm making a BBS from scratch in bash, but I can't seem to get the login working: 'if' is lying to me.

#!/bin/bash
echo "Enter user id:"
read id
if [ $id > $(cat /bbs/howmanyusers) ]; then
        echo "ERROR: non existant user!"
        exit
fi
#The rest of the script in unimportant in this case.

Whatever I input, it always outputs "ERROR: non existant user!" and exits. The output of cat /bbs/howmanyusers is 2.

Help?

Upvotes: 1

Views: 61

Answers (3)

agc
agc

Reputation: 8406

Replace '>' with '-gt'.

Example, compare '\>' to '-gt'.

[ 32 \> 212  ]   && echo yes || echo no
yes
[ 32 -gt 212  ] && echo yes || echo no
no

Reason being the default data format in shell script is an ASCII string. The '\>' in shell script sorts the left side ('32') and right side ('212') strings by ASCII values, and returns 'true' if the left side string has a higher value; '-gt' compares the integer values of the strings.

 man ascii | grep -A 1 062
   062   50    32    2                           162   114   72    r
   063   51    33    3                           163   115   73    s

Upvotes: 2

Gordon Davisson
Gordon Davisson

Reputation: 125798

In addition to the string vs. integer comparison problem, there's actually a second problem nobody has pointed out: > isn't even being treated as a comparison operator, it's being treated as an output redirection! For example:

$ [ a > z ] && echo yes || echo no
yes
$ ls z
z

[ a > z ] is being treated as the test command [ a ] with output redirected to a file named "z". The test command [ a ], meanwhile, means "is 'a' a non-blank string?", and the answer is "yes". Not even slightly close to what you wanted.

BTW, this means you probably have an empty file named "2" in whatever the script's working directory was.

The correct way to do string comparison is to either quote or escape the >, or use bash's [[ ]] (which has cleaner syntax) instead of the old-style [ ]:

$ [ a '>' z ] && echo yes || echo no
no
$ [[ a > z ]] && echo yes || echo no
no

And as others have pointed out, for integer comparison use either [ -gt ] or bash's (( > )):

$ [ 10 -gt 2 ] && echo yes || echo no
yes
$ (( 10 > 2 )) && echo yes || echo no
yes

Upvotes: 1

sentientmachine
sentientmachine

Reputation: 357

When you make numerical comparisons instead of >, < operators is better if you use : -gt as >, -lt as <, -ge as >= and -le as <=.

So it becomes :

if [ $id -gt $(cat /bbs/howmanyusers) ]; then
    ... code ...

Upvotes: 1

Related Questions