Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why "[ 1 > 2 ]" evaluates to True?

Tags:

linux

bash

I have two files:
f1.txt:

1

dest/f1.txt:

1
2

When I run wc -l on both of those files in linux terminal - I get my expected results:

$ wc -l < f1.txt
$ 1
$ wc -l < dest/f1.txt
$ 2

But when I run the following .sh file:

#!/bin/bash

    if [ $(wc -l < f1.txt) > $(wc -l < dest/f1.txt) ]; then
        echo -e "f1 has more lines"
    else
        echo -e "f1 doesn't have more lines"
    fi

The output is:

f1 has more lines            

Can you explian how could this be possible?

like image 733
John Avatar asked Dec 06 '25 09:12

John


2 Answers

You should use the -gt for integer comparison in a if clause.

If you use > or < you will end up doing ASCII alphabetic order comparison.

integer comparison

-eq is equal to

if [ "$a" -eq "$b" ]

-ne is not equal to

if [ "$a" -ne "$b" ]

-gt is greater than

if [ "$a" -gt "$b" ]

-ge is greater than or equal to

if [ "$a" -ge "$b" ]

-lt is less than

if [ "$a" -lt "$b" ]

-le is less than or equal to

if [ "$a" -le "$b" ]

< is less than (within double parentheses)

(("$a" < "$b"))

<= is less than or equal to (within double parentheses)

(("$a" <= "$b"))

> is greater than (within double parentheses)

(("$a" > "$b"))

>= is greater than or equal to (within double parentheses)

(("$a" >= "$b"))

string comparison

= is equal to

if [ "$a" = "$b" ]

Caution
Note the whitespace framing the =.

if [ "$a"="$b" ] is not equivalent to the above.

== is equal to

if [ "$a" == "$b" ]

This is a synonym for =.

Note    
The == comparison operator behaves differently within a double-brackets test than within single brackets.
[[ $a == z* ]]   # True if $a starts with an "z" (pattern matching).
[[ $a == "z*" ]] # True if $a is equal to z* (literal matching).

[ $a == z* ]     # File globbing and word splitting take place.
[ "$a" == "z*" ] # True if $a is equal to z* (literal matching).

!= is not equal to

if [ "$a" != "$b" ]

This operator uses pattern matching within a [[ ... ]] construct.

< is less than, in ASCII alphabetical order

if [[ "$a" < "$b" ]]

if [ "$a" \< "$b" ]

Note that the "<" needs to be escaped within a [ ] construct.

> is greater than, in ASCII alphabetical order

if [[ "$a" > "$b" ]]

if [ "$a" \> "$b" ]

Note that the ">" needs to be escaped within a [ ] construct.

-z string is null, that is, has zero length

String=''   # Zero-length ("null") string variable.

if [ -z "$String" ]
then
  echo "\$String is null."
else
  echo "\$String is NOT null."
fi     # $String is null.

-n
string is not null.

Source: http://tldp.org/LDP/abs/html/comparison-ops.html

like image 50
Allan Avatar answered Dec 08 '25 22:12

Allan


[ is also a command in Bash so [ 1 > 2 ] is the same as [ 1 ] > 2 which would succeed and create a file named 2.

As others pointed out you need to use the following syntax to compare integers:

[ 1 -gt 2 ]
[[ 1 -gt 2 ]]
(( 1 > 2 ))
like image 30
pynexj Avatar answered Dec 08 '25 21:12

pynexj



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!