5 diff.pl -- Helper to diff files (rights, acl and content)
9 diff.pl -s source -d dest [--acl | --attr | --wattr]
16 no warnings 'File::Find';
22 use POSIX qw/strftime/;
24 my ($src, $dst, $help, $acl, $attr, $wattr, $dest_attrib, $src_attrib);
30 GetOptions("src=s" => \$src, # source directory
31 "dst=s" => \$dst, # dest directory
32 "acl" => \$acl, # acl test
33 "attr" => \$attr, # attributes test
34 "wattr" => \$wattr,# windows attributes
36 ) or pod2usage(-verbose => 1,
39 pod2usage(-verbose => 1,
44 pod2usage(-verbose => 2,
47 my $md5 = Digest::MD5->new;
51 chdir($src) or die "E: Can't access to $src";
53 find(\&wanted_src, '.');
56 $src_attrib = `attrib /D /S`;
57 $src_attrib = strip_base($src_attrib, $src);
62 chdir($dst) or die "E: Can't access to $dst";
64 find(\&wanted_src, '.');
67 $dest_attrib = `attrib /D /S`;
68 $dest_attrib = strip_base($dest_attrib, $dst);
70 if (lc($src_attrib) ne lc($dest_attrib)) {
72 print "E: Differences between windows attributes\n",
73 "$src_attrib\n=========\n$dest_attrib\n";
77 #print Data::Dumper::Dumper(\%src_attr);
78 #print Data::Dumper::Dumper(\%dst_attr);
80 foreach my $f (keys %src_attr)
82 if (!defined $dst_attr{$f}) {
84 print "E: Can't find $f in dst\n";
87 compare($src_attr{$f}, $dst_attr{$f});
93 foreach my $f (keys %dst_attr)
96 print "E: Can't find $f in src\n";
100 print "ERROR: found $ret error(s)\n";
105 # convert \ to / and strip the path
108 my ($data, $path) = @_;
110 $data =~ s!\Q$path!!sig;
117 my ($f1, $f2) = ($h1->{file}, $h2->{file});
119 foreach my $k (keys %$h1) {
120 if (!exists $h2->{$k}) {
122 print "E: Can't find $k for dest $f2 ($k=$h1->{$k})\n";
124 if (!defined $h2->{$k}) {
126 print "E: $k not found in destination ", $h1->{file}, "\n";
127 print Data::Dumper::Dumper($h1, $h2);
128 } elsif ($h2->{$k} ne $h1->{$k}) {
130 my ($val1, $val2) = ($h1->{$k}, $h2->{$k});
133 (map { strftime('%F %T', localtime($_)) } ($val1, $val2));
135 print "E: src and dst $f2 differ on $k ($val1 != $val2)\n";
140 foreach my $k (keys %attr) {
142 print "E: Found $k on dst file and not on src ($k=$h2->{$k})\n";
150 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
151 $atime,$mtime,$ctime,$blksize,$blocks) = lstat($f);
153 my $target = readlink($f);
154 $hash->{$File::Find::name} = {
161 file => $File::Find::name,
166 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
167 $atime,$mtime,$ctime,$blksize,$blocks) = stat($f);
170 $hash->{$File::Find::name} = {
178 file => $File::Find::name,
181 open(FILE, '<', $f) or die "Can't open '$f': $!";
183 $hash->{$File::Find::name}->{md5} = $md5->addfile(*FILE)->hexdigest;
187 $hash->{$File::Find::name}->{acl} = `getfacl "$f" 2>/dev/null`;
190 $hash->{$File::Find::name}->{attr} = `getfattr "$f" 2>/dev/null`;
194 $hash->{$File::Find::name} = {
200 file => $File::Find::name,
203 $hash->{$File::Find::name}->{acl} = `getfacl "$f" 2>/dev/null`;
206 $hash->{$File::Find::name}->{attr} = `getfattr "$f" 2>/dev/null`;
209 } else { # other than file and directory