指定フォルダ内の重複ファイルを検出するプログラム
指定したフォルダ内の(サブフォルダ内も含む)全てのファイル名とサイズを取得し、同じサイズのファイル同士を比較して、内容が全く同じファイルを検出するPerlスクリプト。
UTF8用なので、ソースコードもUTF8にする必要がある。Shift-JISにする場合は、"¥"を"\"に置き換える処理で2バイト文字が化ける可能性があるので、2バイト文字コードの一部を誤認しないよう処理を変える必要がある。
#! C:/Perl/bin/perl 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 } # ファイル比較後、重複ファイルの組み合わせをリストで返す sub binary_compare { my @file_list = @_; my @same_list = (); for (my $i = 0; $i + 1 < @file_list; $i++) { for (my $j = $i + 1; $j < @file_list; $j++) { my $diff = 0; # ファイル同士を比較し、同じなら組み合わせをリストに追加する $diff = compare($file_list[$i], $file_list[$j]); push (@same_list, [$file_list[$i], $file_list[$j]]) if ($diff == 0); } } 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) } # ファイルサイズを取得し、サイズ別のハッシュにまとめる # 仕組み : ハッシュ{ファイルサイズ} = [ファイル名1, ファイル名2, ...] 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(@{$files}); # 重複ファイルがある場合、組み合わせを全て表示する foreach my $same_files (@{$same_list}) { printf ("%s == %s (%d B)\n", $same_files->[0], $same_files->[1], $file_size); } }