All pastes #401291 Raw Edit

Unnamed

public text v1 · immutable
·published 2007-03-19 07:00 UTC
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);
}