#/usr/bin/perl # # Usage: lndir old-dir new-dir # # Compare two directories, and link all identical files. # Check args && fetch names. ((($olddir,$newdir) = @ARGV) == 2 && -d $olddir && -d $newdir) || die "Usage: $0 old-dir new-dir\n"; # Get all files in the new dir. open(FIND,"find $newdir -type f -print|"); $|=1; FILE: while ($new = ) { chop $new; ($file = $new) =~ s#^$newdir/##o || die "find said $new?\n"; $old = "$olddir/$file"; # Get stat info for both files. ($ndev,$nino,$nmode,$nnlink,$nuid,$ngid,$nrdev,$nsize, $natime,$nmtime,$nctime,$nblksize,$nblocks) = stat($new); unless ($nino) { print "$new: $!\n"; next FILE; } unless (-f _) { warn "$new is not a plain file\n"; next FILE; } ($odev,$oino,$omode,$onlink,$ouid,$ogid,$ordev,$osize, $oatime,$omtime,$octime,$oblksize,$oblocks) = stat($old); unless ($oino) { next FILE; } unless (-f _) { warn "$old is not a plain file\n"; next FILE; } # Quick check on size and mode. if ($nsize != $osize) { print "$file differs\n"; next FILE; } if ($nmode != $omode) { print "$file mode differs\n"; next FILE; } # Already linked? (Perhaps symbolically?) # Compare dev/inode numbers. if ($ndev == $odev && $nino == $oino) { print "$file already linked\n"; next FILE; } # Now compare the two files. unless (open(NEW,"$new")) { print "$new: $!\n"; next FILE; } unless (open(OLD,"$old")) { print "$old: $!\n"; next FILE; } $blksize = $nblksize || 8192; while (read(OLD,$obuf,$blksize)) { read(NEW,$nbuf,$blksize); if ($obuf ne $nbuf) { print "$file differs\n"; next FILE; } } # Okay, let's link. if (unlink($new) && link($old, $new)) { print "$file linked to $old\n"; next FILE; } print "$file: $!\n"; }