#!/usr/bin/perl
# use strict;
use File::Compare;

# AUTHOR: Jeff Jonas  jeffj@panix.com

# WHY I WROTE THIS: while administering my home system,
# I make copies/snapshots of stuff and want to verify that the copy is ok.
#
# This checks "are all files in A also in B"
# This is NOT commutative / associative ???
# consider:
#	directory "a" contains c1.c c2.c c3.c c4.c
#	directory "b" contains c1.c c2.c c3.c
# where c1.c c2.c and c3.c compare ok in both directories.
# "cmpp b a" will succeed saying all 3 files are the same, but
# "cmpp a b" will also note that there's no c4.c in b.
# So always list the "subset" directory first!


# ### add: -v for "comparing 1 to 2 ..." ok / DIFFER!
# add: option for "cmp -l" to show ALL diffs
# add: option to pass stuff to find kinda like -o "...."
# add: useful return code

# PERHAPS:
# an option for "all a in b" "all b in a" "both ways"
# lists "files in a only ..."
# lists "files in b only ..."

# add: a way just to list FILES IN COMMON
#     ex: delete all files in both snap1/... and snap2/...
#     kinda like "dupp" but lists ONLY those in both, consistently
#     UMMMM, how's that better?


# nice GetOpt examples:
# http://www.aplawrence.com/Unix/perlgetopts.html

use Getopt::Std;
%options=();
getopts("s",\%options);
# getopt("s",\%options);

my $usage = "NO ARGS!\
usage: $0 directory_1 directory_2\ntest if all regular files in a are in b\n";

die $usage if ($#ARGV != 1);

die "$ARGV[0] is not a directory\n" if (! -d $ARGV[0]);
die "$ARGV[1] is not a directory\n" if (! -d $ARGV[1]);

print "recursive cmp of $ARGV[0] to $ARGV[1]\n";

open (pipefd, "cd $ARGV[0]; find . -type f -print |");
	# change to the directory before the find
	# so all pathnames are relative

my ($filecount) = 0;  # count just for stats
my ($match) = 0;
my ($filemissing) = 0;
my ($differ) = 0;
my ($nm1, $nm2);
while (<pipefd>)
{
    $filecount++;

    chomp;
    $_ =~ s/^.//;  # take out find's leading ".", but leave the "/"
    $nm1 = $ARGV[0] . $_;
    $nm2 = $ARGV[1] . $_;
    # print "comparing $nm1 to $nm2 ...\n";
    if (! -f $nm2)
    {
	print "$nm2: does not exist\n";
	$filemissing++;
    }
    else
    {
	if (compare ($nm1, $nm2) == 0)
	{
	    $match++;
	    print "SAME: $_\n" if defined $options{s};
	}
	else
	{
	    print "DIFFER: $nm1 $nm2\n";
	    $differ++;
	}
    }
}

close (pipefd);

if ($filecount == $match)
{
    print "$filecount files ALL MATCH\n";
    exit 0;
}
else
{
    print "$filecount files considered\n";
    print "$match matched\n";
    print "$differ differed\n";
    print "$filemissing missing their counterpart\n";
    exit $filemissing + $differ;
}
