rendered paste body#!/usr/bin/perl
use Switch;
use Digest::MD5;
use Cwd;
@DIR1="";
@DIR2="";
$REPORT="";
$DESTROY="";
$USAGE="Usage: $0 [-h] [-destroy] [-r reportName] -c ControlDir -d Directory1 [ Directory2 Directory3 ... ]\n\t-c ControlDir\t\tSet the control dir (the directory to check against)\n\t-r ReportName\t\tCreate a report of duplicates in file ReportName\n\t-destroy\t\tDelete duplicates in NON-control directories.\n\t-h\t\t\tPrint this help message.\n";
#************************************************************
# This method creates an array containing the LS file we want
#************************************************************
sub makeMD5Hash {
my @directory=();
if ( $#_ == -1 ) {
$directory[0]= $_[0];
} else {
push @directory , @_;
}
my $currentDir = "./";
%returnVal=();
for( $lo=0; $lo < $#directory +1; $lo++ ) {
print "Generating hash data for $directory[$lo]\n";
$ls_cmd = "ls -R $directory[$lo]";
open (LS_CMD, "$ls_cmd |") or die "Couldn't run \"$ls_cmd\"!\n";
while(<LS_CMD>) {
chomp;
#if it's a directory it'll end in a :
if ( $_ =~ /:$/ ) {
$currentDir=$_;
$currentDir=~ s/://g;
} else {
if ( -f "$currentDir/$_" ) {
open(FILE, "$currentDir/$_") or die "Couldn't open \"$currentDir/$_\n";
binmode(FILE);
$returnVal{"$currentDir/$_"}=Digest::MD5->new->addfile(*FILE)->hexdigest;
close(FILE);
}
}
}
close (LS_CMD);
}
return %returnVal;
}
#*********************************************
# Finds potential recursive subdirectory loops
#*********************************************
sub checkSubdir {
my @DIRECTORIES = @_;
my $CWD = getcwd;
for ($i = 0; $i < $#DIRECTORIES+1; $i++) {
for($j=$i+1; $j < $#DIRECTORIES+1; $j++) {
#if we're not the same directory
if( "$DIRECTORIES[$i]" ne "$DIRECTORIES[$j]" ) {
$first = $CWD ."/". $DIRECTORIES[$i];
$second = $CWD ."/". $DIRECTORIES[$j];
if( $first =~ /[^\/]$/ ) {
$first = $first . "/";
}
if( $second =~ /[^\/]$/ ) {
$second = $second . "/";
}
if( index($first,$second,0) != -1 ) {
print "Error: Subdirectories found!\n";
print "\t$first\n\t$second!\n";
exit 1;
}
if( index($second,$first,0) != -1 ){
print "Error: Subdirectories found!\n";
print "\t$second\n\t$first\n";
exit 1;
}
}
}
}}
#**************************
#Get command line arguments
#**************************
for ($i=0; $i < $#ARGV+1; $i++) {
$arg= $ARGV[$i];
$arg=~ s/-//g;
switch ($arg) {
case "r" {
if ( $i == $#ARGV ) {
print "Error: -r expects an argument.\n";
exit 1;
}
$i++;
$REPORT=$ARGV[$i];
}
case "c" {
if ( $i == $#ARGV ) {
print "Error: -c expects an argument.\n";
exit 1;
}
$i++;
$DIR1[0]= $ARGV[$i];
if ( ! -d $DIR1[0] ) {
print "Error: $DIR1[0] is not a valid directory!\n";
exit 1;
}
}
case "destroy" {
$DESTROY=1;
}
else {
print "$USAGE";
exit 1;
}
}
}
if ( "$DESTROY" ne "" ) {
print "WARNING: This is potentially destructive. \n";
print "\tThis will remove all duplicates from non-control directories!\n\n";
print "Are you SURE you want to do this? (yes/no): ";
$answer=<STDIN>;
if( $answer =~ /^[yY][eE][sS]$/ ) {
print "Destroy mode enabled!\n"
} else {
print "Turning off destroy mode!\n";
$DESTROY="";
}
}
print "Checking @DIR1\n";
# Remove the trailing / that the directories may have
for ($i = 0; $i < $#DIR1+1; $i++) {
if ( $DIR1[$i] =~ /\/$/ ) {
$DIR1[$i] =~ /(.+)\/$/;
$DIR1[$i] = $1;
}
}
%md5Hash1 = makeMD5Hash(@DIR1);
%md5Hash2 = %md5Hash1;
print "\nFinding duplicates:\n\n";
#find our duplicates
@keys1 = keys %md5Hash1;
for ( $h1 = 0; $h1 < $#keys1 + 1; $h1++) {
$foundAny=0;
#delete the item we're on so we don't check it
delete $md5Hash2{$keys1[$h1]};
@keys2 = keys %md5Hash2;
for ($h2 = 0; $h2 < $#keys2+1; $h2++) {
if ( "$md5Hash1{$keys1[$h1]}" eq "$md5Hash2{$keys2[$h2]}" ) {
if ( $foundAny == 0 ) {
$duplicates{$keys1[$h1]} .= "$keys2[$h2]";
$foundAny=1;
} else {
$duplicates{$keys1[$h1]} .= ":$keys2[$h2]";
}
#remove the value so we don't get duplicates of duplicates of du..
delete $md5Hash2{$keys2[$h2]};
}
}
}
@keys= keys %duplicates;
if ( "$REPORT" ne "" ) {
open(REPORT,">$REPORT") or die "Error: Couldn't open $REPORT for writing!";
}
for( $i = 0; $i < $#keys+1; $i++) {
print "Duplicates of $keys[$i]:\n";
if ( "$REPORT" ne "" ) { print REPORT "Duplicates of ",getcwd,"/$keys[$i]\n"; }
@temp = split(/:/,$duplicates{$keys[$i]});
for( $j = 0; $j < $#temp+1; $j++) {
if ( "$DESTROY" ne "" ) {
print "\tDestroying $temp[$j]\n";
unlink $temp[$j];
if ( "$REPORT" ne "" ) {
print REPORT "\t",getcwd,"/$temp[$j] Destroyed!\n";
}
} else {
print "\t$temp[$j]\n";
if ( "$REPORT" ne "" ) { print REPORT "\t",getcwd,"/$temp[$j]\n"; }
}
}
print "\n";
if ( "$REPORT" ne "" ) { print REPORT "\n"; }
}
if ( "$REPORT" ne "" ) {
close(REPORT);
}