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";
}
}
|