Recipe 8.22 Comparing the Contents of Two Files

8.22.1 Problem

You have two files and want to see whether they're the same or different.

8.22.2 Solution

Use the standard File::Compare module with filenames, typeglobs, or any indirect filehandles:

use File::Compare;

if (compare($FILENAME_1, $FILENAME_2) =  = 0) {
  # they're equal

if (compare(*FH1, *FH2) =  = 0) {
  # they're equal

if (compare($fh1, $fh2) =  = 0) {
  # they're equal

8.22.3 Discussion

The File::Compare module (standard as of v5.8 and available on CPAN if you have an earlier version of Perl) compares two files for equality. The compare function, exported by default, returns 0 when the files are equal, 1 when they differ, and -1 when any error occurs during reading.

To compare more than two filehandles, simply loop, comparing two at a time:

# ensure all filehandles in @fh hold the same data
foreach $fh (@fh[1..$#fh]) {
  if (compare($fh[0], $fh)) {
    # $fh differs

If you want details of exactly how two files differ, use the Text::Diff module from CPAN:

use Text::Diff;

$diff = diff(*FH1, *FH2);
$diff = diff($FILENAME_1, $FILENAME_2, { STYLE => "Context" });

In addition to filehandles, diff can also take filenames, strings, and even arrays of records. Pass a hash of options as the third argument. The STYLE option controls the type of output returned; it can be "Unified" (the default), "Context", or "OldStyle". You can even write your own class for custom diff formats.

The value returned by diff is a string similar to the output of the diff(1) program. This string is in valid diff format, suitable for feeding into patch(1). Although Text::Diff will not always produce the same output as GNU diff, byte for byte, its diffs are nevertheless correct.

8.22.4 See Also

The documentation for the standard File::Compare module; the documentation for the CPAN module Text::Diff; the diff(1) and patch(1) manpages.