web-dev-qa-db-ja.com

異なる名前の重複ファイルを検索して削除する

大容量の音楽コレクションをハードドライブに保存しています。調べてみると、いくつかのアルバムディレクトリに重複したファイルがたくさんあることがわかりました。通常、重複は元のディレクトリと同じディレクトリに存在します。

通常、形式はfilename.mpで、重複ファイルはfilename 1.mpです。場合によっては、複数の重複ファイルが存在する可能性があり、フォルダ間で重複ファイルがあるかどうか(たとえば、アルバムディレクトリの重複)がわかりません。

これらの重複ファイルをスキャンして(たとえば、ファイルサイズを比較したり、ファイル全体を比較して同一かどうかを確認したり)、結果を確認してから重複を削除する方法はありますか?長い名前を持つもの、またはより最近変更/作成された日付を持つものは、通常、削除の対象になります。

Linuxでこれを実行できるプログラムはありますか?

7
Cestarian

そのようなプログラムがあり、それはrdfindと呼ばれます:

SYNOPSIS
   rdfind [ options ] directory1 | file1 [ directory2 | file2 ] ...

DESCRIPTION
   rdfind  finds duplicate files across and/or within several directories.
   It calculates checksum only if necessary.  rdfind  runs  in  O(Nlog(N))
   time with N being the number of files.

   If  two  (or  more) equal files are found, the program decides which of
   them is the original and the rest are considered  duplicates.  This  is
   done  by  ranking  the  files  to each other and deciding which has the
   highest rank. See section RANKING for details.

重複を削除したり、シンボリックリンクやハードリンクに置き換えたりできます。

12
Toby Speight

ふん。私は、この重複であることが判明した質問のために、すべての重複をリストするワンライナーを開発しました。なんてメタ。まあ、それを無駄にするのは残念なので、私はそれを投稿しますが、rdfindはより良い解決策のように思えます。

これには少なくとも、「実際の」Unixの方法であるという利点があります;)

find -name '*.mp3' -print0 | xargs -0 md5sum | sort | uniq -Dw 32

パイプラインを分解する:

find -name '*.mp3' -print0現在のディレクトリから始まるサブツリー内のすべてのmp3ファイルを検索し、NUL区切りの名前を出力します。

xargs -0 md5sum NULで区切られたリストを読み取り、各ファイルのチェックサムを計算します。

あなたはsortが何をするか知っています。

uniq -Dw 32は、ソートされた行の最初の32文字を比較し、同じハッシュを持つものだけを出力します。

したがって、すべての重複のリストが作成されます。その後、削除したいものまで手動で削って、ハッシュを削除し、リストをrmにパイプします。

10
Tom Zych

rdfindを使用して作業が完了してよかったです。

次回は rmlint も検討できます。これは非常に高速で、複製の各セットの元のファイルを判別するのに役立ついくつかの異なる オプション を提供します。

2
SeeSpotRun

私はPerlの使用を考えています:

#!/usr/bin/Perl
use strict;
use warnings;

use File::Find;
use Digest::SHA qw ( sha1_hex );

my %seen;

sub find_dupes {
    next if -d;
    local $/;
    open( my $input, "<", $File::Find::name ) or warn $!;
    my $sha1sum = sha1_hex(<$input>);
    close($input);
    if ( $seen{$sha1sum} ) {
        print "$File::Find::name is probably a dupe of $seen{$sha1sum} - both have $sha1sum\n";
    }
    $seen{$sha1sum} = $File::Find::name;
}

find( \&find_dupes, "/path/to/search", "/another/path/to/search" );
2
Sobrique