Cách xóa các tệp trùng lặp bằng bash


10

Tôi có một thư mục chứa các tệp trùng lặp (bởi md5sum( md5trên máy Mac)) và tôi muốn có một thư mục công việc theo lịch trình để loại bỏ bất kỳ tìm thấy.

Tuy nhiên, tôi bế tắc về cách làm điều này. Những gì tôi có cho đến nay:

md5 -r * | sort

Mà xuất ra một cái gì đó như thế này:

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

Làm cách nào tôi có thể xử lý dựa trên MD5 của tệp để loại bỏ trùng lặp? Tôi không thực sự quan tâm cái "nguyên bản" nào tôi giữ - nhưng tôi chỉ muốn giữ một cái.

Tôi có nên tiếp cận điều này theo một cách khác?


3
Đã có một fdupeslệnh sẽ thực hiện việc này ... Không chắc bạn đang sử dụng bản phân phối nào, nhưng nó nằm trong gói Debian có cùng tên. Ngoài ra, MD5 là một hàm băm khá yếu hiện nay; bạn có thể muốn sử dụng sha256sum hoặc tốt hơn sha512sum(nên thực sự nhanh hơn trên phần cứng máy tính thông thường)
derobert

1
@derobert - Tôi biết MD5 là một hàm băm yếu, nhưng nó đơn giản và đủ tốt để so sánh các tệp nhỏ :)
warren

tốt, các va chạm MD5 được biết đến và có thể tạo ra với sức mạnh CPU khá khiêm tốn và có một lệnh bạn có thể thay thế để sử dụng SHA-512 thay vào đó, vì vậy ...
derobert

@derobert - Tôi hiểu rằng có những tiêu cực tiềm ẩn khi sử dụng md5 .. nhưng nó quá đủ trong kịch bản này (muốn đảm bảo tôi không có các tệp trùng lặp trong một thư mục nhất định)
warren

1
Đủ công bằng. Điểm chính của bình luận là chỉ ra fdupes.
derobert

Câu trả lời:


3

Tôi đang làm việc trên Linux, có nghĩa là lệnh md5sumxuất ra:

> 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

Bây giờ sử dụng awkxargslệnh sẽ là:

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

Phần awkkhởi tạo lasthashvới chuỗi rỗng, sẽ không khớp với bất kỳ hàm băm nào, sau đó kiểm tra từng dòng nếu hàm băm lasthashgiống như hàm băm (cột đầu tiên) của tệp hiện tại (cột thứ hai). Nếu có, nó sẽ in ra. Ở cuối mỗi bước, nó sẽ được đặt thành lasthashhàm băm của tệp hiện tại (bạn có thể giới hạn chỉ được đặt nếu băm khác nhau, nhưng đó chỉ là một vấn đề nhỏ đặc biệt là nếu bạn không có nhiều tệp phù hợp). Các tên tập tin awk spits ra được làm thức ăn cho rmxargs, mà về cơ bản gọi rmvới những gì awkphần cho chúng ta.

Bạn có thể cần phải lọc các thư mục trước md5sum *.

Biên tập:

Sử dụng phương pháp Marcins bạn cũng có thể sử dụng phương pháp này:

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

Các chất nền từ filelist được lấy bằng lstên tệp đầu tiên của mỗi hàm băm duy nhất được lấy bởi md5sum * | sort -k1 | uniq -w 32 | awk '{print $2}'.


1
cảm ơn: md5 -r * | sort -t ' ' -k 4 -r | awk 'BEGIN{lasthash = ""} $1 == lasthash {print $2} {lasthash = $1}' | xargs rmlà lời kêu gọi trên OS X (theo gợi ý của @ Stephen Kitt , tôi đã đặt echo 'will remove 'ở cuối trước khi dùng thử rm)
warren

Có lẽ bạn nên chỉnh sửa câu hỏi của mình vì giải pháp đã cho không khớp với kết quả đầu ra mà bạn đã đưa ra.
Stephen Kitt

1
Và bạn nên đổi sort -t ' ' -k 4 -rsang sort.
Tristan Storch

@TristanStorch - điểm tốt :)
warren

Điều này giả định rằng bạn không có khoảng trắng trong tên tệp của mình, một giả định nguy hiểm trong mọi trường hợp. (Và đặc biệt để cho các OP đang sử dụng một máy Mac Tôi dám bạn để tìm một máy Mac, bất kỳ máy Mac, mà không có tên tập tin không gian chứa ở tất cả..) :)
Wildcard

7

Bạn có thể xác định các tệp trùng lặp bằng lệnh sau:

md5sum * | sort -k1 | uniq -w 32 -d

1
Điều này chỉ xuất ra một tệp cho mỗi bộ trùng lặp. Nếu bạn muốn xóa tất cả các bản sao và chỉ giữ lại một bản sao, bạn có thể giữ những bản sao bạn nhận được bằng lệnh này và xóa phần còn lại
golimar

2

Tôi đã chạy qua fdupes như một câu trả lời cho câu hỏi tương tự này: /superuser/386199/how-to-remove-d repeatated-files-in-a-irectory

Tôi đã có thể apt-get install fdupestrên Ubuntu. Bạn chắc chắn sẽ muốn đọc trang người đàn ông. Trong trường hợp của tôi, tôi đã có thể nhận được kết quả mong muốn như vậy:

fdupes -qdN -r /ops/backup/

Trong đó có nội dung "xem đệ quy thông qua / ops / backup và tìm tất cả các tệp trùng lặp: giữ bản sao đầu tiên của bất kỳ tệp đã cho nào và lặng lẽ xóa phần còn lại." Điều này làm cho nó rất dễ dàng để giữ một số cơ sở dữ liệu ghi không thường xuyên.


1

Nếu bạn đang vội (hoặc bạn có nhiều tệp) và muốn tránh chi phí hoạt động (mất nhiều thời gian) nhưng đừng bận tâm đến chi phí bộ nhớ của bảng băm (hoặc bạn có nhiều ram với số lượng lớn của các tập tin),

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: Tìm tất cả các tệp và xuất chúng với tên kết thúc null

xargs -0 md5sum: tính toán các giá trị băm song song (điều chỉnh -nmax-args và -Pmax-procs theo ý muốn, xem man xargs)

awk 'h[$1]{ printf "%s\0", $2; next }{ h[$1] = $2 }': nếu có một mục trong hàm băm awk có chứa md5sum mà chúng ta hiện đang xem, sau đó in ra tên tệp mà chúng ta hiện đang xem, kết thúc bằng null. Nếu không, thêm tên tệp vào bảng băm.

xargs -0 rm: lấy các chuỗi kết thúc null được nạp vào và gửi chúng đến rm.

Đây là cách nhanh hơn fdupes.

Nếu bạn có một tên tệp có chứa một dòng mới, awk có thể sẽ cắt nó ở dòng mới vì md5sum cũng tách các bản ghi theo dòng mới.

Điều này dựa trên /programming/11532157/remove-d repeatate-lines-without-summing/programming/9133315/how-can-i-output-null-terminated- chuỗi-in-awk


1
md5sum * | sort -k1 | uniq -w 32 -d | cut -d' ' -f3 | xargs -I{} sh -c 'rm {}'
  1. lấy tất cả các giá trị md5
  2. sắp xếp chúng sao cho dupes là tuần tự cho uniq
  3. chỉ chạy uniq để sao chép đầu ra
  4. cắt tên tệp từ dòng có giá trị md5
  5. liên tục xóa cuộc gọi trên tên tập tin

0
comm -13 <(md5sum * | sort | uniq -w 32 -d) <(md5sum * | sort | uniq -w 32 -D) | cut -f 3- -d" " | xargs -d '\n' rm

Đặc trưng:

  • Vẫn hoạt động nếu có nhiều hơn một bản sao trên mỗi tệp
  • Vẫn hoạt động nếu tên tệp có khoảng trắng
  • Vẫn hoạt động nếu bạn có bí danh lsvới một loại hoặc--color=always
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.