Вот общий алгоритм (отредактированный для эффективности теперь, когда я стряхнул сонные снаряды - и я также исправил ошибку, о которой никто не сообщал) ...:)
Это займет вечность (не говоря уже о большом количестве памяти), если я сравню содержимое каждого отдельного файла со всеми остальными. Вместо этого, почему бы сначала не применить один и тот же поиск к их размерам, а затем сравнить контрольные суммы для этих файлов одинакового размера.
Итак, когда мы md5sum каждого файла (см. Дайджест :: MD5 ) вычисляем их размеры, мы можем использовать хеш-таблицу, чтобы сделать наше сопоставление для нас, сохраняя совпадения вместе в массиве:
use strict;
use warnings;
use Digest::MD5 qw(md5_hex);
my %files_by_size;
foreach my $file (@ARGV)
{
push @{$files_by_size{-s $file}}, $file; # store filename in the bucket for this file size (in bytes)
}
Теперь нам нужно просто извлечь потенциальные дубликаты и проверить, одинаковы ли они (создав контрольную сумму для каждого, используя Digest :: MD5 ), используя ту же технику хеширования:
while (my ($size, $files) = each %files_by_size)
{
next if @$files == 1;
my %files_by_md5;
foreach my $file (@$files_by_md5)
{
open my $filehandle, '<', $file or die "Can't open $file: $!";
# enable slurp mode
local $/;
my $data = <$filehandle>;
close $filehandle;
my $md5 = md5_hex($data);
push @{$files_by_md5{$md5}}, $file; # store filename in the bucket for this MD5
}
while (my ($md5, $files) = each %files_by_md5)
{
next if @$files == 1;
print "These files are equal: " . join(", ", @$files) . "\n";
}
}
-fini