Cara menghapus file duplikat menggunakan bash

10

Saya memiliki folder dengan duplikat (oleh md5sum( md5pada Mac)) file, dan saya ingin memiliki pekerjaan dijadwalkan untuk menghapus yang ditemukan.

Namun, saya terjebak pada bagaimana melakukan ini. Apa yang saya miliki sejauh ini:

md5 -r * | sort

Yang menghasilkan sesuatu seperti ini:

04c5d52b7acdfbecd5f3bdd8a39bf8fb gordondam_en-au11915031300_1366x768.jpg
1e88c6899920d2c192897c886e764fc2 fortbourtange_zh-cn9788197909_1366x768.jpg
266ea304b15bf4a5650f95cf385b16de nebraskasupercell_fr-fr11286079811_1366x768.jpg
324735b755c40d332213899fa545c463 grossescheidegg_en-us10868142387_1366x768.jpg
3993028fcea692328e097de50b26f540 Soyuz Spacecraft Rolled Out For Launch of One Year Crew.png
677bcd6006a305f4601bfb27699403b0 lechaustria_zh-cn7190263094_1366x768.jpg
80d03451b88ec29bff7d48f292a25ce6 ontariosunrise_en-ca10284703762_1366x768.jpg
b6d9d24531bc62d2a26244d24624c4b1 manateeday_row10617199289_1366x768.jpg
ca1486dbdb31ef6af83e5a40809ec561 Grueling Coursework.jpg
cdf26393577ac2a61b6ce85d22daed24 Star trails over Mauna Kea.jpg
dc3ad6658d8f8155c74054991910f39c smoocave_en-au10358472670_1366x768.jpg
dc3ad6658d8f8155c74054991910f39c smoocave_en-au10358472670_1366x7682.jpg

Bagaimana saya bisa memproses berdasarkan MD5 file untuk menghapus duplikat? Saya tidak benar-benar peduli yang "asli" Saya terus - tapi aku hanya ingin menyimpan satu.

Haruskah saya mendekati ini dengan cara yang berbeda?

warren
sumber
3
Sudah ada fdupesperintah yang akan melakukan ini ... Tidak yakin distro mana yang Anda gunakan, tetapi itu dalam paket Debian dengan nama yang sama. Juga, MD5 adalah hash yang cukup lemah saat ini; Anda mungkin ingin menggunakan sha256sum atau lebih baik sha512sum(yang sebenarnya harus lebih cepat pada perangkat keras PC normal)
derobert
1
@derobert - Saya tahu MD5 adalah hash yang lemah, tetapi sederhana dan cukup baik untuk membandingkan file-file kecil :)
warren
Yah, tabrakan MD5 dikenal dan dihasilkan dengan jumlah daya CPU yang cukup sederhana, dan ada perintah yang bisa Anda gantikan untuk menggunakan SHA-512 sebagai gantinya, jadi ...
derobert
@derobert - Saya mengerti ada potensi negatif untuk menggunakan md5 .. tapi ini lebih dari cukup dalam skenario ini (ingin memastikan saya tidak memiliki file duplikat di direktori yang diberikan)
warren
1
Cukup adil. Poin utama dari komentar ini adalah untuk menunjukkan fdupes.
derobert

Jawaban:

3

Saya bekerja di Linux, yang artinya adalah perintah md5sumyang menghasilkan:

> md5sum *
d41d8cd98f00b204e9800998ecf8427e  file_1
d41d8cd98f00b204e9800998ecf8427e  file_10
d41d8cd98f00b204e9800998ecf8427e  file_2
d41d8cd98f00b204e9800998ecf8427e  file_3
d41d8cd98f00b204e9800998ecf8427e  file_4
d41d8cd98f00b204e9800998ecf8427e  file_5
d41d8cd98f00b204e9800998ecf8427e  file_6
d41d8cd98f00b204e9800998ecf8427e  file_7
d41d8cd98f00b204e9800998ecf8427e  file_8
d41d8cd98f00b204e9800998ecf8427e  file_9
b026324c6904b2a9cb4b88d6d61c81d1  other_file_1
31d30eea8d0968d6458e0ad0027c9f80  other_file_10
26ab0db90d72e28ad0ba1e22ee510510  other_file_2
6d7fce9fee471194aa8b5b6e47267f03  other_file_3
48a24b70a0b376535542b996af517398  other_file_4
1dcca23355272056f04fe8bf20edfce0  other_file_5
9ae0ea9e3c9c6e1b9b6252c8395efdc1  other_file_6
84bc3da1b3e33a18e8d5e1bdd7a18d7a  other_file_7
c30f7472766d25af1dc80b3ffc9a58c7  other_file_8
7c5aba41f53293b712fd86d08ed5b36e  other_file_9

Sekarang menggunakan awkdan xargsperintahnya adalah:

md5sum * | \
sort | \
awk 'BEGIN{lasthash = ""} $1 == lasthash {print $2} {lasthash = $1}' | \
xargs rm

Bagian awkdiinisialisasi lasthashdengan string kosong, yang tidak akan cocok dengan hash apa pun, dan kemudian memeriksa untuk setiap baris jika hash di lasthashsama dengan hash (kolom pertama) dari file saat ini (kolom kedua). Jika ya, itu akan mencetaknya. Pada akhir setiap langkah itu akan diatur lasthashke hash dari file saat ini (Anda dapat membatasi ini hanya diatur jika hash berbeda, tetapi itu harus menjadi hal kecil terutama jika Anda tidak memiliki banyak file yang cocok). Nama file awk meludah keluar dimasukkan ke rmdengan xargs, yang pada dasarnya panggilan rmdengan apa yang awkbagian memberi kita.

Anda mungkin perlu memfilter direktori sebelumnya md5sum *.

Edit:

Menggunakan metode Marcins Anda juga bisa menggunakan yang ini:

comm -1 -2 \
  <(ls) | \
  <(md5sum * | \
    sort -k1 | \
    uniq -w 32 | \
    awk '{print $2}' | \
    sort) \
xargs rm

Subtract ini dari daftar file yang dipilih oleh lsnama file pertama dari setiap hash unik yang dipilih oleh md5sum * | sort -k1 | uniq -w 32 | awk '{print $2}'.

Tristan Storch
sumber
1
terima kasih: md5 -r * | sort -t ' ' -k 4 -r | awk 'BEGIN{lasthash = ""} $1 == lasthash {print $2} {lasthash = $1}' | xargs rmadalah panggilan di OS X (sesuai saran Stephen Kitt , saya letakkan echo 'will remove 'di bagian akhir sebelum mencobanya rm)
warren
Anda mungkin harus mengedit pertanyaan Anda karena solusi yang diberikan tidak sesuai dengan contoh hasil yang Anda berikan.
Stephen Kitt
1
Dan Anda harus berubah sort -t ' ' -k 4 -rmenjadi sort.
Tristan Storch
@TristanStorch - tempat yang bagus :)
warren
Ini mengasumsikan Anda tidak memiliki spasi dalam nama file Anda, asumsi berbahaya dalam keadaan apa pun. (Dan terutama mengingat OP menggunakan Mac. Saya berani Anda menemukan Mac, Mac apa pun, yang tidak memiliki nama file yang mengandung ruang sama sekali.) :)
Wildcard
7

Anda dapat mengidentifikasi file duplikat menggunakan perintah berikut:

md5sum * | sort -k1 | uniq -w 32 -d
Marcin
sumber
1
Ini menghasilkan hanya satu file untuk setiap set duplikat. Jika Anda ingin menghapus semua duplikat dan hanya menyimpan satu, Anda dapat menyimpan yang Anda dapatkan dengan perintah ini dan menghapus sisanya
golimar
2

Saya menemukan fdupes sebagai jawaban untuk pertanyaan serupa ini: /superuser/386199/how-to-remove-duplicated-files-in-a-directory

Saya bisa apt-get install fdupesdi Ubuntu. Anda pasti ingin membaca halaman manual. Dalam kasus saya, saya bisa mendapatkan hasil yang diinginkan seperti:

fdupes -qdN -r /ops/backup/

Yang mengatakan "lihat secara rekursif melalui / ops / backup dan temukan semua file duplikat: simpan salinan pertama dari file yang diberikan, dan diam-diam hapus sisanya." Ini membuatnya sangat mudah untuk menyimpan beberapa dump dari database yang jarang-menulis.

dannyman
sumber
1

Jika Anda sedang terburu-buru (atau Anda memiliki banyak file) dan ingin menghindari overhead semacam (itu membutuhkan waktu) tetapi tidak keberatan memori overhead tabel hash (atau Anda memiliki banyak ram dengan banyak Anda file),

find . -type f -print0 | xargs -0 md5sum | awk 'h[$1]{ printf "%s\0", $2; next }{ h[$1] = $2 }' | xargs -0 rm

find . -type f -print0: Temukan semua file dan hasilkan dengan nama yang diakhiri null

xargs -0 md5sum: menghitung hash secara paralel (sesuaikan -nmax-args dan -Pmax-procs seperti yang diinginkan, lihat man xargs)

awk 'h[$1]{ printf "%s\0", $2; next }{ h[$1] = $2 }': jika ada entri di hask awk yang berisi md5sum yang sedang kita lihat, kemudian cetak nama file yang sedang kita lihat, null-terminated. Jika tidak, tambahkan nama file ke tabel hash.

xargs -0 rm: ambil string yang diakhiri dengan piped-in null dan kirimkan ke rm.

Ini jauh lebih cepat daripada fdupes.

Jika Anda memiliki nama file yang berisi baris baru, awk mungkin akan memotongnya di baris baru karena md5sum memisahkan catatan dengan baris baru juga.

Ini didasarkan pada /programming/11532157/remove-duplicate-lines-without-sorting dan /programming/9133315/how-can-i-output-null-terminated- string-in-awk

Alex
sumber
1
md5sum * | sort -k1 | uniq -w 32 -d | cut -d' ' -f3 | xargs -I{} sh -c 'rm {}'
  1. ambil semua nilai md5
  2. urutkan mereka sehingga dupes berurutan untuk uniq
  3. jalankan uniq hanya untuk menghasilkan dupes
  4. memotong nama file dari baris dengan nilai md5
  5. berulang kali memanggil hapus pada nama file
Carter Cole
sumber
0
comm -13 <(md5sum * | sort | uniq -w 32 -d) <(md5sum * | sort | uniq -w 32 -D) | cut -f 3- -d" " | xargs -d '\n' rm

Fitur:

  • Masih berfungsi jika ada lebih dari satu duplikat per file
  • Masih berfungsi jika nama file memiliki spasi
  • Masih berfungsi jika Anda memiliki alias lsatau sejenisnya--color=always
Alex Lamson
sumber