Tìm tập tin trùng lặp


90

Có thể tìm thấy các tệp trùng lặp trên đĩa của tôi giống hệt nhau từ bit đến bit nhưng có tên tệp khác nhau không?


3
Lưu ý rằng mọi phương pháp có thể thực hiện việc này sẽ luôn phải so sánh mọi tệp duy nhất trên hệ thống của bạn với mọi tệp khác . Vì vậy, điều này sẽ mất nhiều thời gian, ngay cả khi dùng phím tắt.
Shadur

4
@Shadur nếu một cái nào đó ổn với tổng kiểm tra, thì nó sẽ chỉ so sánh các giá trị băm - mà trên hầu hết các hệ thống có thứ tự 10 ^ (5 + -1) thường <các mục 64 byte. Tất nhiên, bạn phải đọc dữ liệu ít nhất một lần. :)
peterph

15
@Shadur Điều đó không đúng. Bạn có thể giảm thời gian bằng cách kiểm tra st_sizes phù hợp , loại bỏ những cái chỉ có một cái giống nhau và sau đó chỉ tính md5sums cho st_sizes phù hợp .
Chris Down

6
@Shadur ngay cả một cách tiếp cận cực kỳ ngớ ngẩn không cho phép bất kỳ thao tác băm nào cũng có thể thực hiện điều này trong Θ (n log n) so sánh không phải (n²) Sử dụng bất kỳ thuật toán sắp xếp nào (dựa trên nội dung tệp).
derobert

1
@ChrisDown Có, khớp kích thước sẽ là một trong những phím tắt tôi có trong đầu.
Shadur

Câu trả lời:


104

fdupescó thể làm điều này Từ man fdupes:

Tìm kiếm đường dẫn đã cho cho các tệp trùng lặp. Các tệp như vậy được tìm thấy bằng cách so sánh kích thước tệp và chữ ký MD5, theo sau là so sánh theo từng byte.

Trong Debian hoặc Ubuntu, bạn có thể cài đặt nó với apt-get install fdupes. Trong Fedora / Red Hat / CentOS, bạn có thể cài đặt nó với yum install fdupes. Trên Arch Linux, bạn có thể sử dụng pacman -S fdupesvà trên Gentoo , emerge fdupes.

Để chạy một kiểm tra giảm dần từ gốc hệ thống tập tin của bạn, việc này có thể sẽ tốn một lượng thời gian và bộ nhớ đáng kể, hãy sử dụng một cái gì đó như fdupes -r /.

Khi được hỏi trong các ý kiến, bạn có thể nhận được các bản sao lớn nhất bằng cách thực hiện như sau:

fdupes -r . | {
    while IFS= read -r file; do
        [[ $file ]] && du "$file"
    done
} | sort -n

Điều này sẽ phá vỡ nếu tên tệp của bạn chứa dòng mới.


Cảm ơn. Làm thế nào tôi có thể lọc ra bản dupe lớn nhất? Làm thế nào tôi có thể làm cho kích thước con người có thể đọc được?
sinh viên

@student: sử dụng một cái gì đó dọc theo dòng (chắc chắn fdupes chỉ xuất ra tên tập tin không có informatinos thêm, hoặc cắt hoặc sed để chỉ giữ đó): fdupes ....... | xargs ls -alhd | egrep 'M |G 'để giữ các tập tin ở định dạng có thể đọc được con người và chỉ những người có kích thước trong MB hoặc Gigabyte. Thay đổi lệnh cho phù hợp với đầu ra thực.
Olivier Dulac

2
@OlivierDulac Bạn không bao giờ nên phân tích ls . Thông thường nó tệ hơn trường hợp sử dụng của bạn, nhưng ngay cả trong trường hợp sử dụng của bạn, bạn cũng có nguy cơ dương tính giả.
Chris Down

@student - Một khi bạn có tên tệp, duđường ống sortsẽ cho bạn biết.
Chris Down

@ChrisDown: đúng là một thói quen xấu và có thể đưa ra những nhận định sai. Nhưng trong trường hợp đó (sử dụng tương tác và chỉ để hiển thị, không có "rm" hoặc bất cứ thứ gì thuộc loại trực tiếp dựa vào nó) thì tốt và nhanh chóng ^^. Tôi yêu những trang mà bạn liên kết đến, btw (đã đọc chúng từ vài tháng nay và có rất nhiều thông tin hữu ích)
Olivier Dulac

26

Một công cụ tốt khác là fslint:

fslint là một bộ công cụ để tìm các vấn đề khác nhau với các hệ thống tệp, bao gồm các tệp trùng lặp và tên tệp có vấn đề, v.v.

Các công cụ dòng lệnh riêng lẻ có sẵn ngoài GUI và để truy cập chúng, người ta có thể thay đổi hoặc thêm vào $ PATH thư mục / usr / share / fslint / fslint trên bản cài đặt tiêu chuẩn. Mỗi lệnh trong thư mục đó có tùy chọn --help để biết thêm chi tiết về các tham số của nó.

   findup - find DUPlicate files

Trên các hệ thống dựa trên debian, bạn có thể cài đặt nó với:

sudo apt-get install fslint

Bạn cũng có thể làm điều này bằng tay nếu bạn không muốn hoặc không thể cài đặt các công cụ của bên thứ ba. Cách thức hoạt động của hầu hết các chương trình như vậy là bằng cách tính toán tổng kiểm tra tệp . Các tệp có cùng md5sum gần như chắc chắn chứa chính xác cùng một dữ liệu. Vì vậy, bạn có thể làm một cái gì đó như thế này:

find / -type f -exec md5sum {} \; > md5sums
gawk '{print $1}' md5sums | sort | uniq -d > dupes
while read d; do echo "---"; grep $d md5sums | cut -d ' ' -f 2-; done < dupes 

Đầu ra mẫu (tên tệp trong ví dụ này giống nhau, nhưng nó cũng sẽ hoạt động khi chúng khác nhau):

$ while read d; do echo "---"; grep $d md5sums | cut -d ' ' -f 2-; done < dupes 
---
 /usr/src/linux-headers-3.2.0-3-common/include/linux/if_bonding.h
 /usr/src/linux-headers-3.2.0-4-common/include/linux/if_bonding.h
---
 /usr/src/linux-headers-3.2.0-3-common/include/linux/route.h
 /usr/src/linux-headers-3.2.0-4-common/include/linux/route.h
---
 /usr/src/linux-headers-3.2.0-3-common/include/drm/Kbuild
 /usr/src/linux-headers-3.2.0-4-common/include/drm/Kbuild
---

Đây sẽ là nhiều chậm hơn so với các công cụ chuyên dụng đã được đề cập, nhưng nó sẽ làm việc.


4
Sẽ nhanh hơn rất nhiều nếu tìm thấy bất kỳ tệp nào có cùng kích thước với một tệp khác bằng cách sử dụng st_size, loại bỏ bất kỳ tệp nào chỉ có một tệp có kích thước này và sau đó chỉ tính toán md5sums giữa các tệp có cùng st_size.
Chris Down

@ChrisDown yeah, chỉ muốn giữ cho nó đơn giản. Tất nhiên những gì bạn đề xuất sẽ tăng tốc mọi thứ lên. Đó là lý do tại sao tôi từ chối trách nhiệm về việc nó bị chậm ở cuối câu trả lời của tôi.
terdon

8

Câu trả lời ngắn gọn: có.

Phiên bản dài hơn: hãy xem mục nhập wikipedia fdupes , nó có một danh sách khá tốt về các giải pháp đã sẵn sàng. Tất nhiên bạn có thể viết riêng của bạn, nó không phải khó khăn - chương trình băm như diff, sha*sum, find, sortuniqnên thực hiện công việc. Bạn thậm chí có thể đặt nó trên một dòng, và nó vẫn sẽ dễ hiểu.


6

Nếu bạn tin rằng hàm băm (ở đây MD5) không va chạm trên miền của bạn:

find $target -type f -exec md5sum '{}' + | sort | uniq --all-repeated --check-chars=32 \
 | cut --characters=35-

Muốn tên tập tin giống hệt nhau được nhóm? Viết một kịch bản đơn giản not_uniq.shđể định dạng đầu ra:

#!/bin/bash

last_checksum=0
while read line; do
    checksum=${line:0:32}
    filename=${line:34}
    if [ $checksum == $last_checksum ]; then
        if [ ${last_filename:-0} != '0' ]; then
            echo $last_filename
            unset last_filename
        fi
        echo $filename
    else
        if [ ${last_filename:-0} == '0' ]; then
            echo "======="
        fi
        last_filename=$filename
    fi

    last_checksum=$checksum
done

Sau đó thay đổi findlệnh để sử dụng tập lệnh của bạn:

chmod +x not_uniq.sh
find $target -type f -exec md5sum '{}' + | sort | not_uniq.sh

Đây là ý tưởng cơ bản. Có lẽ bạn nên thay đổi findnếu tên tệp của bạn có chứa một số ký tự. (ví dụ: không gian)


6

Tôi nghĩ sẽ thêm một nhánh fdupes, jdupes được cải tiến gần đây , hứa hẹn sẽ nhanh hơn và nhiều tính năng hơn fdupes (ví dụ: bộ lọc kích thước):

jdupes . -rS -X size-:50m > myjdups.txt

Điều này sẽ đệ quy tìm các tệp trùng lặp lớn hơn 50MB trong thư mục hiện tại và xuất danh sách kết quả trong myjdups.txt.

Lưu ý, đầu ra không được sắp xếp theo kích thước và vì nó dường như không được xây dựng, tôi đã điều chỉnh câu trả lời @Chris_Down ở trên để đạt được điều này:

jdupes -r . -X size-:50m | {
    while IFS= read -r file; do
        [[ $file ]] && du "$file"
    done
} | sort -n > myjdups_sorted.txt

Lưu ý: phiên bản mới nhất của jdupes hỗ trợ các tệp phù hợp chỉ với một phần băm thay vì chờ để băm toàn bộ. Rất hữu ích. (Bạn phải sao chép kho lưu trữ git để lấy nó.) Đây là tùy chọn tôi đang sử dụng ngay bây giờ: jdupes -r -T -T --exclude = size-: 50m --nohidden
Benjamin

2

Wikipedia đã có một bài viết ( http://en.wikipedia.org/wiki/List_of_d repeatate_file_finder ), với một danh sách các phần mềm nguồn mở có sẵn cho nhiệm vụ này, nhưng hiện tại nó đã bị xóa .

Tôi sẽ thêm rằng phiên bản GUI của fslint rất thú vị, cho phép sử dụng mặt nạ để chọn tệp nào cần xóa. Rất hữu ích để làm sạch hình ảnh trùng lặp.

Trên Linux, bạn có thể sử dụng:

- FSLint: http://www.pixelbeat.org/fslint/

- FDupes: https://en.wikipedia.org/wiki/Fdupes

- DupeGuru: https://www.hardcoded.net/dupeguru/

Hai công việc cuối cùng trên nhiều hệ thống (windows, mac và linux) Tôi chưa kiểm tra FSLint


5
Tốt hơn là cung cấp thông tin thực tế ở đây và không chỉ là một liên kết, liên kết có thể thay đổi và sau đó câu trả lời không còn giá trị
Anthon

2
Trang Wikipedia trống.
ihor_dvoretskyi

vâng, nó đã được làm sạch, thật đáng tiếc ...
MordicusEtCubitus

Tôi đã chỉnh sửa nó bằng 3 công cụ này
MordicusEtCubitus

0

Đây là của tôi về điều đó:

find -type f -size +3M -print0 | while IFS= read -r -d '' i; do
  echo -n '.'
  if grep -q "$i" md5-partial.txt; then echo -e "\n$i  ---- Already counted, skipping."; continue; fi
  MD5=`dd bs=1M count=1 if="$i" status=noxfer | md5sum`
  MD5=`echo $MD5 | cut -d' ' -f1`
  if grep "$MD5" md5-partial.txt; then echo "\n$i  ----   Possible duplicate"; fi
  echo $MD5 $i >> md5-partial.txt
done

Điều khác biệt ở chỗ nó chỉ băm tối đa 1 MB đầu tiên của tệp.
Điều này có một số vấn đề / tính năng:

  • Có thể có sự khác biệt sau 1 MB đầu tiên vì vậy kết quả là một ứng cử viên cần kiểm tra. Tôi có thể sửa nó sau.
  • Kiểm tra theo kích thước tập tin đầu tiên có thể tăng tốc độ này.
  • Chỉ mất các tệp lớn hơn 3 MB.

Tôi sử dụng nó để so sánh các video clip vì vậy điều này là đủ cho tôi.

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.