find_dupes.pl

`

############################################################
# find_dupes.pl: Welche evtl. identischen Dateien habe ich?
############################################################
use strict;
use File::Find;

my %CheckedSums;
my @xxlFiles;
my $too_large = 20000000;
my $Newline = "\n";
############################################################
# Ausgabe: Ergebnisliste
############################################################
sub print_dupes
{
	my $trennlinie = "-" x 20 . "$Newline";
	print "Dateien wurden untersucht.$Newline";
	print "Möglicherweise identisch:$Newline", $trennlinie;
	my $keine = "(Keine identischen Dateien gefunden.)$Newline" . $trennlinie;

	for(sort keys %CheckedSums)	
	{
		if(scalar split("$Newline", $CheckedSums{$_} ) > 1)
		{
			print $CheckedSums{$_}, $trennlinie;
			$keine = "$Newline";
		}
	}
	print $keine;
	if(scalar @xxlFiles > 1)
	{
	print "${Newline}Folgende ", scalar @xxlFiles,
	" Dateien wurden nicht verglichen, weil sie sehr gross sind:";
	print $trennlinie;
	print join("$Newline", @xxlFiles), "$Newline";

	}
}

############################################################
# Checksumme ermitteln
############################################################

sub checksum_file
{
	local $/; # Slurp-Mode - ganze Datei einsaugen, nicht zeilenweise
	open my $handle, $_ or return -1;
	my $retval = unpack("%32C*", <$handle>) % 65535;
	close $handle;
	return $retval;
}

############################################################
# Groessen+Summen feststellen + in Ergebnisliste schreiben
############################################################
sub check_files
{
	unless (-f)
	{
	# bei Verzeichnissen abbrechen
	return;
	}

	# Eigenschaften der gefundenen Datei auslesen
	my ($dev, $inode, $mode, $numlinks, $uid, $gid, $rdev, $size, $whatever)
	= stat($_) or return;

	unless($size <= 0 || $size > $too_large)
	{
		my $checksum = checksum_file($_);
		unless($checksum < 0)
		{
			my $CheckID = sprintf("%032d %032d", $size, $checksum);
			$CheckedSums{$CheckID} .= $File::Find::name . "$Newline";
		}
	}

	if($size > $too_large)
	{
		push(@xxlFiles, $File::Find::name);
	}

}

############################################################
# Hauptprogramm
############################################################

if ($#ARGV < 0)
{
	die "Bitte mindestens einen Pfad angeben!$Newline";
}

for(@ARGV)
{
	chomp;

	if(! -d)
	{
	print "$_ wurde nicht gefunden oder ist kein Verzeichnis.$Newline$Newline";
	next;
	}
	find(\&check_files, $_);
	print_dupes();
}

############################################################
# EOF
############################################################
`

2 Gedanken zu „find_dupes.pl

  1. Anstatt $Newline kannst du auch die vordefinierte Variable $\ verwenden. Übrigens wäre es ja noch eine Idee, nur Dateien zu vergleichen, die gleich gross sind, denn unterschiedlich grosse Dateien sind garantiert keine Dupes … :-)

  2. Ich such hier aber nicht nach Dupes zu einer bestimmten Datei, sondern Duplikate, die in einem Verzeichnisbaum herumlungern. Gut, ich könnte mir zu den einzelnen Dateien nur die Größe merken, und die Prüfsumme dann erst bei Bedarf feststellen. Dazu bräuchte ich dann zwei Hashes: Eins mit Größen, und eins mit Prüfsummen. … Lass ich mir mal durch den Kopf gehen.

    $Newline hatte übrigens nen ganz faulen Grund: ich wollte die vielen Backslashes in meinem Blog-Eintrag vermeiden. ;-)

Kommentare sind geschlossen.