指定フォルダ内の重複ファイルを検出するプログラムの修正
指定フォルダ内の重複ファイルを検出するプログラムを参照の事。
サイズ0のファイルが検出されたり、3つ以上の重複ファイルが2つ以上の組み合わせに分かれていたりと、大量のファイルを扱うには不便な箇所が色々と見つかったので、修正。
空のファイルを無視し、3つ以上の重複ファイルを一纏めにして表示するように変更した。
use utf8; use strict; use warnings; use File::Find::Iterator; use File::Compare; # File::Find::Iterator my $find; # filter用サブルーチン sub isdir { -d } sub isfile { -f -s } # ファイル比較後、重複ファイルの組合わせをハッシュで返す。 sub binary_compare { my @file_list = @_; my $same_list = {}; my @dub_files = (); for (my $i = 0; $i + 1 < @file_list; $i++) { next if (grep ($file_list[$i], @dub_files) > 0); for (my $j = $i + 1; $j < @file_list; $j++) { my $diff = 0; $diff = compare($file_list[$i], $file_list[$j]); if ($diff == 0) { if (exists $same_list->{$file_list[$i]}) { push @{$same_list->{$file_list[$i]}}, $file_list[$j]; } else { $same_list->{$file_list[$i]} = [$file_list[$j]]; } push @dub_files, $file_list[$j]; } } } return $same_list; } # ベースディレクトリ(指定なしの場合カレントディレクトリ) my $base_dir = $ARGV[0] || './'; # 区切り文字'\'を'/'に変換する $base_dir =~ s/\\/\//gso; # ファイル一覧取得 my @file_list; $find = File::Find::Iterator->create(dir => [$base_dir], filter => \&isfile); while (my $f = $find->next) { push (@file_list, $f) } my %file_size_hash_table = (); foreach my $file_name (@file_list) { my $file_size = -s $file_name; $file_size_hash_table{$file_size} = [] unless exists $file_size_hash_table{$file_size}; push @{$file_size_hash_table{$file_size}}, $file_name; } foreach my $file_size (sort keys %file_size_hash_table) { my $files = $file_size_hash_table{$file_size}; next unless (@{$files} > 1); my $same_list = binary_compare(sort @{$files}); foreach my $same_files_head (sort keys %{$same_list}) { my $same_files = $same_list->{$same_files_head}; print $same_files_head; foreach my $same_file (@$same_files) { print ' == ' . $same_file; } print '(' . $file_size . ' B)' . "\n"; } }