use Digest::MD5 qw(md5); use strict; my %files=(); my %dateien; my @nulllength=(); my @dateisize=(); my @dateien=get_all_files('c:/htdocs/',1,'.shtml'); print "Es wurden ".@dateien." Dateien gefunden\n"; ## Dateilänge holen und merken foreach (@dateien){ open (my $IN,'<'.$_); my $dateilaenge=(stat($_))[7]; binmode ($IN); read ($IN,my $key,100); close $IN; my $size="$dateilaenge|$key"; # Ist Hash-Element der Dateigröße schon vorhanden??? # Wenn nicht, dann Array anlegen, erster Wert ist die Dateigröße # Übrigens : Hier kann man die Verwendung eines Hashes mit (aus?) Arrays sehen push (@{$dateien{$size}},"$size") if (!defined @{$dateien{$size}}); push (@{$dateien{$size}},$_); } # Ab hir steht in [filename,filename,filename] # jede Datei, aufgetielt nach Dateigroessen @dateien=(); foreach (keys %dateien){ my @dats=@{$dateien{$_}}; # wenigstens 2 Filenamen müssen da sein, also @dats >= 3, da erster Eintrag die Dateilaenge next if @dats < 3; &get_checksum(@dats); } %dateien=(); print qq~Dateien mit Nulllaenge:\n~; print join("\n",@nulllength); print qq~\n\nIdentische Dateien:\n~; foreach (keys %files){ print "$files{$_}\n\n" if (split('\n',$files{$_}) >1); } exit; ################### # Parameter # Startdir ohne abschließendes /, aktuelles Verzeichnis = . # Unterverzeichnisse durchsuchen? 1: ja, 0: nein # Dateitypen in form .txt.htm.html , also direkt hintereinander, aber nur wenn nötig # ansonsten wird alles gezeigt ############################################# sub get_all_files{ my $startdir=shift; my $include_subdirs=shift; my $endings=shift; my %endings=(); $endings=~ s/\s//g; my @endings=split('\.',$endings); shift @endings; my $endings=0; $startdir=~ s/\/$//; if (@endings != 0){ $endings=1; # wenn Endungen angegeben foreach (@endings){ $endings{$_}=1; } } @endings=(); my @dateien=(); push (my @all_directories,$startdir); foreach my $akdir(@all_directories){ local *in; opendir (in,$akdir); my @all=readdir(in); closedir in; foreach my $akdatei (@all){ next if ($akdatei eq '..' || $akdatei eq '.'); if (-d "$akdir/$akdatei") { if ($include_subdirs == 1){ push (@all_directories,"$akdir/$akdatei"); next; } } else { if ($endings==0){ push (@dateien,"$akdir/$akdatei"); } else { my @endung=split('\.',$akdatei); my $endung=$endung[-1]; if ($endings{$endung} == 1){ push (@dateien,"$akdir/$akdatei"); } } } } } return @dateien; } ###################### # generiert Checksumme einer Datei ############################################# sub get_checksum{ my ($dateiname,$dateilaenge); my %tempfiles=(); # temporäre Files my $data=''; $dateilaenge=shift; ($dateilaenge,my $dummy)=split('\|',$dateilaenge); return if $dateilaenge > 64000000; if ($dateilaenge == 0){ # Wenn Dateilaenge = 0, dann gleich alles ins Array und zurück push (@nulllength,@_); return; } my $firsthundret=''; foreach $dateiname (@_){ open (my $IN,'<'.$dateiname); binmode($IN); my $checksum = Digest::MD5->new->addfile(*$IN)->digest; close $IN; $files{$checksum}.="$dateiname\n"; } } |