use strict;
use warnings;
use Digest::MD5 qw(md5);

# Hash fuer Dateinamen und Checksum
# Key ist die Checksum, Value ist ein
# anonymes Array von Dateinamen
my %filelist = ();

my ($key, $name, $startdir);

# Verzeichnis wird auf der Kommandozeile uebergeben
die "Usage: $0 <verzeichnis>\n" unless (@ARGV);

$startdir = shift;
# ggf. / am Ende wegmachen
$startdir =~ s|/$||;

# Hash erstellen
scanfiles($startdir);

# Und das Ergebnis ausgeben
print "\nDateien mit identischer MD5-Pruefsumme:\n";
for $key(keys(%filelist))
  {
  if(@{$filelist{$key}} > 1)
    {
    print join (' = ',@{$filelist{$key}}), "\n";
    }
  }


sub scanfiles
  {
  # Scannt recursiv ein Verzeichnis, das als
  # Parameter uebergeben wird
  my $scandir = shift;
  my (@scandirs, @files, $file, $list, $actfile, $chk);
  # Verzeichnis einlesen, alle unterverzeichnisse specheern
  opendir(DIR,$scandir) || warn "Kann Directory $scandir nicht lesen: $!\n";
  @scandirs = grep {!(/^\./) && -d "$scandir/$_"} readdir(DIR);
  # desgleichen für alle Daten im aktuellen Verzeichnis
  rewinddir(DIR);
  @files = grep {!(/^\./) && -f "$scandir/$_"} readdir(DIR);
  closedir (DIR);
  # Unterverzeichnisse rekursiv abarbeiten
  for $list(0 .. $#scandirs)
    {
    &scanfiles($scandir."/".$scandirs[$list]);
    }
  # Dateien im aktuellen Verzeichnis in die Liste aufnehmen
  if ($#files >= 0)
    {
    print "Bearbeite Verzeichnis $scandir\n";
    for $file(@files)
      {
      $actfile = $scandir.'/'.$file;
      $chk = checksum($actfile);
      push(@{$filelist{$chk}},$actfile);
      }
    }
  }


sub checksum
  {
  # ermittelt den MD5-Hash einer Datei (hexadezimal)
  my $datei = shift;
  my $size = -s($datei);
  return (0) if ($size <1);
  open(FILE, '<', $datei) or die "Can't open '$datei': $!";
  binmode(FILE);
  my $chck = Digest::MD5->new->addfile(*FILE)->hexdigest;
  close FILE;
  return($chck);
  }