Làm thế nào để so sánh các phần của tập tin bằng hàm băm?


19

Tôi có một tệp được tải xuống thành công và một tệp tải xuống không thành công (chỉ 100 MB đầu tiên của một tệp lớn) mà tôi nghi ngờ là cùng một tệp.

Để xác minh điều này, tôi muốn kiểm tra giá trị băm của họ, nhưng vì tôi chỉ có một phần của tệp được tải xuống không thành công, tôi chỉ muốn băm vài megabyte đầu tiên hoặc lâu hơn.

Làm thế nào để tôi làm điều này?

Hệ điều hành sẽ là windows, nhưng tôi đã cài đặt Cygwin và MinGW.


1
So sánh hiệu quả một tệp trên máy tính cục bộ với một tệp khác trên máy tính ở xa là một phần quan trọng của rsync , so sánh các phần của tệp với hàm băm đặc biệt.
David Cary

@DavidCary Trong trường hợp của tôi, tôi không có quyền truy cập shell vào máy tính từ xa, nhưng nhờ gợi ý, tôi sẽ đọc trang này
sinned

Câu trả lời:


56

Tạo băm để so sánh các tệp có ý nghĩa nếu bạn so sánh một tệp với nhiều tệp hoặc khi so sánh nhiều tệp với nhau.

Sẽ không có ý nghĩa khi chỉ so sánh hai tệp một lần: Nỗ lực tính toán các giá trị băm ít nhất là cao bằng cách đi qua các tệp và so sánh trực tiếp chúng.

Một công cụ so sánh tập tin hiệu quả là cmp:

cmp --bytes $((100 * 1024 * 1024)) file1 file2 && echo "File fragments are identical"

Bạn cũng có thể kết hợp nó với dd để so sánh các phần tùy ý (không nhất thiết phải từ đầu) của hai tệp, ví dụ:

cmp \
    <(dd if=file1 bs=100M count=1 skip=1 2>/dev/null) \
    <(dd if=file2 bs=100M count=1 skip=1 2>/dev/null) \
&& echo "File fragments are identical"

6
Lưu ý: tạo băm để so sánh các tệp cũng có ý nghĩa nếu bạn muốn tránh đọc hai tệp cùng một lúc.
Kamil Maciorowski

1
@KamilMaciorowski Vâng, đúng. Nhưng phương pháp này thường sẽ vẫn nhanh hơn so với so sánh băm trong trường hợp cặp.
Konrad Rudolph

8
Đây là giải pháp để đi. cmp là 99,99% chắc chắn đã được cài đặt nếu bạn có bash chạy, và nó làm công việc. Thật, cmp -n 131072 one.zip two.zip cũng sẽ làm công việc Ít ký tự nhất để gõ, và thực hiện nhanh nhất. Tính toán một hàm băm là vô nghĩa. Nó yêu cầu toàn bộ tệp 100 MB để được đọc, thêm một phần 100 MB của tập tin hoàn chỉnh, điều này là vô nghĩa. Nếu chúng là các tệp zip và chúng khác nhau, sẽ có một sự khác biệt trong vài trăm byte đầu tiên. Readahead cung cấp 128k theo mặc định, vì vậy bạn cũng có thể so sánh 128k (chi phí tương tự như so sánh 1 byte).
Damon

19
Các --bytes tùy chọn chỉ làm phức tạp nhiệm vụ. Chỉ cần chạy cmp không có tùy chọn này và nó sẽ hiển thị cho bạn byte đầu tiên khác nhau giữa các tệp. Nếu tất cả các byte là như nhau thì nó sẽ hiển thị EOF trên tập tin ngắn hơn. Điều này sẽ cung cấp cho bạn nhiều thông tin hơn ví dụ của bạn - có bao nhiêu byte là chính xác.
pabouk

2
Nếu bạn có GNU cmp (và, tôi nghĩ rằng hầu hết mọi người đều làm như vậy), bạn có thể sử dụng --ignore-initial--bytes tranh luận thay vì làm phức tạp mọi thứ với các yêu cầu dd.
Christopher Schultz

12

Tôi xin lỗi tôi không thể chính xác thử điều đó, nhưng cách này sẽ hiệu quả

dd if=yourfile.zip of=first100mb1.dat bs=100M count=1
dd if=yourotherfile.zip of=first100mb2.dat bs=100M count=1

Điều này sẽ giúp bạn có 100 Megabyte đầu tiên của cả hai tệp.

Bây giờ có được băm:

sha256sum first100mb1.dat && sha256sum first100mb2.dat 

Bạn cũng có thể chạy nó trực tiếp:

dd if=yourfile.zip bs=100M count=1 | sha256sum 
dd if=yourotherfile.zip bs=100M count=1 | sha256sum 

1
Có cách nào để dẫn dd bằng cách nào đó vào sha256sum mà không cần tệp trung gian không?
sinned

1
Tôi đã thêm một cách khác theo yêu cầu của bạn
davidbaumann

8
Tại sao tạo băm? Điều đó kém hiệu quả hơn nhiều so với việc chỉ so sánh trực tiếp các đoạn tập tin (sử dụng cmp ).
Konrad Rudolph

Trong mẫu mã giữa của bạn, bạn nói First100mb1.dat hai lần. Ý của bạn là 100mb 2 .dat cho cái thứ hai?
doppelgreener

@KonradRudolph, "Tại sao tạo băm?" Giải pháp của bạn (sử dụng cmp ) là một người chiến thắng mà không có nghi ngờ. Nhưng cách giải quyết vấn đề này (sử dụng băm) cũng có quyền tồn tại miễn là nó thực sự giải quyết được vấn đề (:
VL-80

7

Mọi người dường như đi theo con đường Unix / Linux với điều này, nhưng chỉ cần so sánh 2 tệp có thể dễ dàng thực hiện với các lệnh chuẩn của Windows:
FC /B file file2

FC có mặt trên mọi phiên bản Windows NT từng được tạo ra. Và (nếu tôi nhớ chính xác) cũng đã có mặt trong DOS.
Nó hơi chậm, nhưng điều đó không quan trọng đối với việc sử dụng một lần.


6

Bạn chỉ có thể so sánh trực tiếp các tệp với chương trình khác biệt nhị phân / hex như vbindiff. Nó nhanh chóng so sánh các tệp lên tới 4GB trên Linux & amp; Các cửa sổ.

Trông giống như thế này, chỉ với sự khác biệt được tô sáng bằng màu đỏ (1B so với 1C):

one                                       
0000 0000: 30 5C 72 A7 1B 6D FB FC  08 00 00 00 00 00 00 00  0\r..m.. ........  
0000 0010: 00 00 00 00                                       ....
0000 0020:
0000 0030:
0000 0040:
0000 0050:
0000 0060:
0000 0070:
0000 0080: 
0000 0090: 
0000 00A0: 

two        
0000 0000: 30 5C 72 A7 1C 6D FB FC  08 00 00 00 00 00 00 00  0\r..m.. ........  
0000 0010: 00 00 00 00                                       ....               
0000 0020: 
0000 0030:
0000 0040:
0000 0050:
0000 0060:
0000 0070:
0000 0080:
0000 0090:                                
0000 00A0:             
┌──────────────────────────────────────────────────────────────────────────────┐
│Arrow keys move  F find      RET next difference  ESC quit  T move top        │
│C ASCII/EBCDIC   E edit file   G goto position      Q quit  B move bottom     │
└──────────────────────────────────────────────────────────────────────────────┘ 

Trong trường hợp của tôi, các tệp là lưu trữ zip, vì vậy không có văn bản có ý nghĩa trong đó. So sánh giá trị băm nên nhanh hơn và ít bị lỗi hơn.
sinned

2
Nếu bạn có nghĩa là văn bản ASCII, thì điều đó không liên quan. vbindiff (và của Konrad cmp ) so sánh dữ liệu nhị phân, byte cho byte. Trong thực tế, các giá trị có nhiều khả năng gặp phải va chạm
Xen2050

* Mete "Trong thực tế HASH các giá trị có nhiều khả năng gặp phải va chạm "trong nhận xét trên, đã bỏ lỡ h!
Xen2050

0

Tôi biết nó nói cho Bash, nhưng OP cũng nói rằng họ có Windows. Đối với bất kỳ ai muốn / yêu cầu giải pháp Windows, có một chương trình có tên HxD là Trình chỉnh sửa Hex có thể so sánh hai tệp. Nếu các tệp có kích thước khác nhau, nó sẽ cho biết các phần có sẵn có giống nhau không. Và nếu cần, nó có khả năng chạy tổng kiểm tra cho bất cứ điều gì hiện đang được chọn. Nó miễn phí và có thể được tải xuống từ: trang web HxD . Tôi không có bất kỳ kết nối nào với (các) tác giả, tôi đã sử dụng nó trong nhiều năm.


0

cmp sẽ cho bạn biết khi hai tệp giống hệt nhau với chiều dài của tệp nhỏ hơn:

$ dd if=/dev/random bs=8192 count=8192 > a
8192+0 records in
8192+0 records out
67108864 bytes transferred in 0.514571 secs (130417197 bytes/sec)
$ cp a b
$ dd if=/dev/random bs=8192 count=8192 >> b 
8192+0 records in
8192+0 records out
67108864 bytes transferred in 0.512228 secs (131013601 bytes/sec)
$ cmp a b
cmp: EOF on a

cmp đang nói với bạn rằng so sánh đã gặp EOF trên tệp a trước khi phát hiện ra bất kỳ sự khác biệt nào giữa hai tệp.


Điểm tốt. Nếu bạn chưa thấy nó, đây là những gì pabouk đã nhận xét về câu trả lời được chấp nhận.
sinned
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.