0

I want in a bash script (Linux) to check, if two files are identical. I use the following code:

#!/bin/bash
… 
…
differ=$(diff $FILENAME.out_ok $FILENAME.out)
echo "******************"
echo $differ
echo "******************"
if [ $differ=="" ]
  then
   echo "pass"
 else
 echo "Error ! different output"  
 echo $differ   
 fi

The problem:

  • the diff command return white space and break the if command

output

 ******************
 82c82 < ---------------------- --- > ---------------------
 ******************
 ./test.sh: line 32: [: too many arguments
 Error ! different output
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
user1675224
  • 213
  • 2
  • 12

3 Answers3

3

The correct tool for checking whether two files are identical is cmp.

if cmp -s $FILENAME.out_ok $FILENAME.out
then : They are the same
else : They are different
fi

Or, in this context:

if cmp -s $FILENAME.out_ok $FILENAME.out
then
    echo "pass"
else
    echo "Error ! different output"
    diff $FILENAME.out_ok $FILENAME.out
fi

If you want to use the diff program, then double quote your variable (and use spaces around the arguments to the [ command):

if [ -z "$differ" ]
then
    echo "pass"
else
    echo "Error ! different output"  
    echo "$differ"   
fi

Note that you need to double quote the variable when you echo it to ensure that newlines etc are preserved in the output; if you don't, everything is mushed onto a single line.

Or use the [[ test:

if [[ "$differ" == "" ]]
then
    echo "pass"
else
    echo "Error ! different output"  
    echo "$differ"   
fi

Here, the quotes are not strictly necessary around the variable in the condition, but old school shell scripters like me would put them there automatically and harmlessly. Roughly, if the variable might contain spaces and the spaces matter, it should be double quoted. I don't see a need to learn a special case for the [[ command when it works fine with double quotes too.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
2

Instead of:

if [ $differ=="" ]

Use:

if [[ $differ == "" ]]

Better to use modern [[ and ]] instead of an external program /bin/[

Also use diff -b to compare 2 files while ignoring white spaces

anubhava
  • 761,203
  • 64
  • 569
  • 643
  • 1
    You can use `diff -b`, but the problem was not the white space in the files; it was the white space (newlines, etc) in the output from `diff` (which appear independently of whether there is a difference in the spacing in the files). The information about `diff -b` is valid; it is just tangential to the issue in the question. Also, although there is an external program `/bin/[`, the shells all use a built-in `[` (aka `test`) command and have done for decades. – Jonathan Leffler Aug 18 '13 at 14:22
  • Agreed that all the legacy code has been using `test or [` for ages but I believe at least newer code should give preference to use `[[` or `((`. Agreed completely with your points on `diff -b` and your recommendation to use cmp. – anubhava Aug 18 '13 at 14:27
  • I haven't yet come to the point where I use `[[` or `((` in preference to `[`; I may get there eventually, but `[` works fine for me most of the time. `[[` has regex matching; that's new and useful. It allows `<` and `>` to mean comparison not I/O redirection, but I've never missed that. AFAICR, using `((` is for arithmetic; it is only coincidentally a way of testing conditions. Like I said, I'm an unreformed (or semi-unreformed) old school programmer. I don't think that the abuse heaped on `[` is fully warranted — it is serviceable as long as you treat it with the respect it should be given. – Jonathan Leffler Aug 18 '13 at 14:36
  • Totally agree with you @JonathanLeffler. Please count me on your side, many times I also end up using `[` myself. – anubhava Aug 18 '13 at 15:41
1

@anubhava answer is correct, you can also use

if [ "$differ" == "" ]
bartimar
  • 3,374
  • 3
  • 30
  • 51
  • Spaces around the == are not optional. – choroba Aug 18 '13 at 14:08
  • @choroba: To get the expected result with the `[`, you must include the spaces. As written without the spaces, it always evaluates to true because with a single operand, `[` checks whether the string is empty, and with the `==` in the string, it never is empty. Nitpicking — your basic statement is accurate. – Jonathan Leffler Aug 18 '13 at 14:14
  • @JonathanLeffler: That was my point. I am probably getting too laconic. – choroba Aug 18 '13 at 14:16