#!/usr/bin/perl
use strict;
use File::Find;
use Digest::file qw(digest_file_hex);
use vars qw/*name *dir *prune/;
*name = *File::Find::name;
*dir = *File::Find::dir;
*prune = *File::Find::prune;
my $kb = 1024;
my $mb = 1048576;
my $gb = 1073741824;
my $dir = '.';
-d $dir or die "Ошибка: Директория \"$dir\" не найдена.";
my %size_file;
my $files_grp_cnt = 0;
my ($files_cnt, $summ_size, $complete_file);
sub bytes_scale {
my $b = $_[0] + 0;
my ($r, $n);
if ($b >= $gb) { $r = $b / $gb; $n = 'G' }
elsif ($b >= $mb) { $r = $b / $mb; $n = 'M' }
elsif ($b >= $kb) { $r = $b / $kb; $n = 'K' }
else { $r = $b; $n = 'B' }
sprintf '%.3g%s', $r, $n;
}
sub add_to_hash {
$size_file{$_[0]}{$_[1]} = '';
}
sub wanted {
my ($dev,$ino,$mode,$nlink,$uid,$gid);
(($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
-f _ && (int(((-s _) + 511) / 512) > 0)
&& \&add_to_hash (-s _, $name);
}
print "Поиск и чтение размеров файлов... ";
File::Find::find({wanted => \&wanted}, $dir);
print "OK\n";
print "Обработка данных... ";
for my $size (keys %size_file) {
my $files = scalar (keys %{$size_file{$size}});
if ($files < 2) {
delete $size_file{$size};
next;
}
$files_cnt += $files;
$files_grp_cnt++;
$summ_size += $size * $files;
}
print "OK\n";
if ($files_grp_cnt == 0) {
print "Не найдено файлов с одинаковым размером.\n";
exit;
}
my $summ_size_scale = &bytes_scale($summ_size);
print "Найдено $files_grp_cnt групп файлов с одинаковым размером.
Всего в группах $files_cnt файлов общим объемом $summ_size_scale\n";
my %size_hash_file;
my $complete_summ_size;
print "Вычисление хэш сумм файлов...\n";
for my $size (keys %size_file) {
for my $file (keys %{$size_file{$size}}) {
my $hash = digest_file_hex($file, 'MD5');
$size_hash_file{$size}{$hash}{$file} = '';
$complete_summ_size += $size;
$complete_file++;
print "\rВычислено $complete_file хэшей файлов из $files_cnt, объемом ", &bytes_scale($complete_summ_size) . " из $summ_size_scale ";
}
}
print "\nOK \n";
my ($dups_exst, $grp, $f_cnt, $all_f_cnt, $all_summ_size);
print "Вывод данных...\n";
for my $size (keys %size_hash_file) {
for my $hash (keys %{$size_hash_file{$size}}) {
next if (scalar (keys %{$size_hash_file{$size}{$hash}}) < 2);
$dups_exst = 1;
$grp++;
$f_cnt = 0;
print "Группа: $grp\n";
for my $file (keys %{$size_hash_file{$size}{$hash}}) {
$f_cnt++;
print " $f_cnt) $file\n";
}
$f_cnt -= 1;
my $grp_size = $size * $f_cnt;
$all_f_cnt += $f_cnt;
$all_summ_size += $grp_size;
print " ", &bytes_scale($size), " x $f_cnt = ", &bytes_scale($grp_size), "\n\n";
}
}
print "Дубликатов не найдено.\n" and exit unless ($dups_exst);
print "=====================================
Всего:
Групп дубликатов: $grp
Дубликатов в группах
(не считая первого оригинального файла в каждой группе):
$all_f_cnt файлов, объемом ", &bytes_scale($all_summ_size), ".\n=====================================\n";