web-dev-qa-db-ja.com

異なるディスクやディレクトリで重複したファイルを見つけて削除する

私は数十万のファイルを多くの外部ディスクとコンピューターのディスクに分散させており、その多くは複製されています。この混乱は、私が安全提案のためにコピーを作成したことが原因でした。時々、組織のディレクトリ構造を変更しましたが、コピーがあった他の場所には複製されませんでした。

今、私は1つの巨大なディスクを持っており、バックアップが本当に必要で、クラウドにミラーリングされています。

すでにビッグディスクにあるすべての分散ディスクからすべてを削除する方法が欲しいのですが。

シナリオを見せてみましょう:

OldDisk1:

/code/{manystructures}/{manyfiles}
/docs/{manystructures}/{manyfiles}

OldDisk2:

/dev/{another_structures}/{same_files_different_names}
/documents/{another_structures}/{same_files_different_names}

NewHugeDisk:

/home/username/code/{new_strutucture}/{new_files}
/home/username/documents/{new_strutucture}/{new_files}

「すでにNewHugeDiskにあるOldDisk1上のすべてのファイルを見つけて削除する」などのツールや方法を知っている人はいますか?

私は多くのツール(Windows、Mac、Linuxの両方でこの問題が発生しているため)を無料と有料で調べましたが、運がありませんでした。

そして、ideiaはそれを行うためのコードを作成するでしょうが、私は開発者ではありません。小さくて単純なコードはできますが、この種のコードは私にとっては複雑になると思います。

これに関する助けやアイデアをいただければ幸いです。

1
Tuts

プロセス全体のOSとしてWindowsを使用でき、 Free Duplicate File Finder (試したことはありませんが、言及されていることがわかりました ここ )が気に入らないと仮定すると、 PowerShellを使用すると、比較的少ない労力で目的を達成できます。注:私はPowerShellの本当のプロではないので、コードを改良できると確信しています。

Powershell ISEを開いて(または、メモ帳がない場合はメモ帳を使用して)、次のコードをコピーして貼り付け、結果のファイルを* .ps1として保存します。また、$oldpath$newpathの値をディレクトリに変更する必要があります。パスを引用符で囲んでください。

# Search-and-Destroy-script
# Get all files of both code-directories:
$oldpath = "Disk1:\code"
$newpath = "DiskNew:\code"

$files_old = Get-ChildItem -Path $oldpath -Recurse -File
$files_new = Get-ChildItem -Path $newpath -Recurse -File

for($i=0; $i -lt $files_old.length; $i++){
    $j=0
    while($true){
        # if last edit time is the same and file-size is the same...
        if($($files_old[$i]).length -eq $($files_new[$j]).length -and $($files_old[$i]).lastWriteTime -eq $($files_new[$j]).lastWriteTime){
            # Get File-Hashes for those files (SHA1 should be enough)
            $files_old_hash = Get-FileHash -Path $($files_old[$i]).FullName -Algorithm SHA1 | ForEach-Object {$_.Hash}
            $files_new_hash = Get-FileHash -Path $($files_new[$j]).FullName -Algorithm SHA1 | ForEach-Object {$_.Hash}
            # if hashes also are the same...
            if($files_old_hash -eq $files_new_hash){
                # remove the old file (-Confirm can be removed so you don't have to approve for every file)
                # if you want to check the files before deletion, you could also just rename them (here we're adding the suffix ".DUPLICATE"
                # Rename-Item -Path $($files_old[$i]).FullName -NewName "$($files_old[$i]).Name.DUPLICATE"
                Remove-Item -Path $($files_old[$i]).FullName -Confirm
                Write-Host "DELETING`t$($files_old[$i]).FullName" -ForegroundColor Red
                break
            }
        # if files aren't the same...
        }else{
            # if old_file is compared to all new_files, check next old file
            if($j -ge $files_new.length){
                break
            }
        }
        $j++
    }
}

次に、スクリプトを開始します(たとえば、右クリックして)-それが失敗した場合は、ExecutionPolicyが設定されていることを確認します( https://superuser.com/a/106363/70324 )。

ほぼ同じスクリプトを使用して、すでにコピーされている(ただし、名前が変更されている可能性がある)ファイルをチェックします。このコードは、ファイルの名前のみが異なり、内容は異なることを前提としています。作成時間とは異なり、ファイルを新しいパスにコピーした後でも、通常、最終編集時間は同じままです。コンテンツが異なる場合、私のソリューションはひどく失敗します-ファイルの異なる一意の属性を使用するか(しかしどれですか?)、または次のように述べることができます。新しいファイルを削除する必要があるファイルよりも小さいか古いファイル(編集時間を考慮して)のみ。

スクリプトの機能:

  1. 指定されたフォルダー(およびそのサブフォルダー)内のすべてのファイルを取得する
  2. 最初の古いファイル($ iで指定)を取得しています...
  3. 最終編集時間とファイルサイズを最初の新しいファイル($ jで指定)のものと比較します。
  4. ...それらが等しい場合は、ファイルハッシュを計算して、それが間違いなく同じファイルであることを確認します(おそらく、これは目標に対して少し手間がかかりすぎる可能性があります)
  5. ハッシュが等しい場合、古いファイルは削除され(そして、ターミナルにどのファイルが書き込まれます)、次の古いファイルで2から再開します。
  6. ハッシュが等しくない場合(または最後の編集時間が等しくないか、ファイルサイズが等しくない場合)、次の新しいファイルで3から再開します。
2
flolilo

rmlint は、必要なことを正確に実行するためのオプションを備えたコマンドラインユーティリティです。 LinuxとmacOSで動作します。必要なコマンドは次のとおりです。

$ rmlint --progress \
    --must-match-tagged --keep-all-tagged \
    /mnt/OldDisk1 /mnt/OldDisk2 // /mnt/NewHugeDisk

これにより、必要な重複が見つかります。それらを直接削除する代わりに、シェルスクリプト(./rmlint.sh)を作成します。このスクリプトを確認し、オプションで編集してから実行すると、目的の削除を実行できます。

'--progress'オプションは、Niceの進行状況インジケーターを提供します。 '//'は、 'タグなし'から 'タグ付き'パスを区切ります。 '//'の後のパスは 'タグ付き'と見なされます。 '--must-match-tagged --keep-all-tagged'は、タグ付きパスにコピーがあるタグなしパス内のファイルのみを検索することを意味します。

オプションの短い形式を使用して、そのコマンドを短縮することもできます。

rmlint -g -m -k /mnt/OldDisk1 /mnt/OldDisk2 // /mnt/NewHugeDisk
0
thomas_d_j

サードパーティの重複排除ソフトウェアを使用してみましたか?
私はcloudberry deduplicationを試しましたが、次のように非常に効率的です。

  • 重複データを排除する独自の重複排除メカニズムを備えているため、多くのストレージスペースを節約できます。
  • このようなツールのもう1つの利点は、信頼性が高く、専用のリソース管理手法を備えていることです。
0
user8010482