Below script is throwing error :

if [[ $(wc -l "/disk1/environment.sh") -ge 0 ]];then  
   echo "File has data"  

line 2: [[: 5 /disk1/environment.sh: division by 0 (error token is "/environment.sh")

But the below code is working fine :

  if [[ $(wc -l "/disk1/environment.sh") > 0 ]];then  
    echo "File has data"  

Could some one please tell me why '-ge' and '>' is behaving different here ?
bash version : GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)


That's because of the output from wc -l /filename, this would output e.g.:

5 /filename

but you are doing integer comparison (operator: -ge), hence the extraneous portion /filename is invalid leading to the error message.

Just pass the filename to wc via STDIN so that wc just returns the count:

[[ $(wc -l </disk1/environment.sh) -ge 0 ]]

In the second case, [[ $(wc -l /disk1/environment.sh) > 0 ]], you are simply checking if the output from command substitution, $(wc -l /disk1/environment.sh), sorts after 0, lexicographically; which will always be the case unless wc returns some error and produces nothing on STDOUT.

Just to note, [[ does not support arithmetic operators like >, >=, <, <=, you need the (( keyword for these:

(( $(wc -l </disk1/environment.sh) > 0 ))

The second attempt doesn't produce an error, but it doesn't work fine, assuming that your attempt is to test whether the file contains at least one line.

The output of wc -l "/disk1/environment.sh" consists of the number of lines in the file, a space and the file name. If you want to use the number of lines, you need to extract it. Rather than split the output, there's an easier way: instead of passing the file name on the command line, redirect the output of wc from the file. Then wc only prints the number with no file name.

if [[ $(wc -l <"/disk1/environment.sh") -ge 0 ]];then  
   echo "File has data"  

Or, since you're using bash syntax anyway,

if (($(wc -l <"/disk1/environment.sh") >= 0)); then  
   echo "File has data"  

Of course this is always true since the number of lines is always greater or equal to 0. But you can get useful results with other numbers.

In your first attempt, you use the -ge operator. This is an operator on integers. You get an error message because the left-hand side is not an integer, but something like 42 /disk1/environment.sh.

In your second attempt, you use the < operator in a conditional statement. This operator is string comparison (in lexical order). It so happens that the output of wc -l /disk1/environment.sh is always ordered lexically after 0, since it starts with a digit, therefore [[ $(wc -l <"/disk1/environment.sh") > 0 ]] is always true. The exception is when /disk1/environment.sh doesn't exist; in this case wc -l produces nothing on standard output (it writes an error message to standard error instead), and the comparison is false.

Comparing the number of lines in a file to 0 is not very useful. On modern systems, wc -l counts the number of newlines. In a text file, the number of newlines is 0 only if the file is empty. (In general wc -l returns 0 if the file doesn't contain any newline character; a text file contains a newline at the end of each line, and the number of newlines in non-text files is rarely useful information.) There's an operator in conditional expressions to test if a file is empty, you don't need to invoke wc.

if [[ ! -e /disk1/environment.sh ]]; then
  if [[ -L /disk1/environment.sh ]]; then
    echo "/disk1/environment.sh is a broken symbolic link"
    echo "/disk1/environment.sh does not exist"
elif [[ ! -r /disk1/environment.sh ]]; then
  echo "/disk1/environment.sh exists but is not readable"
elif [[ ! -s /disk1/environment.sh ]]; then
  echo "/disk1/environment.sh is empty or is a special file (name pipe, etc.)"
  echo "/disk1/environment.sh is not empty"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.