วิธีเปรียบเทียบส่วนต่าง ๆ ของไฟล์ด้วยแฮช


19

ฉันมีไฟล์ที่ดาวน์โหลดสำเร็จหนึ่งไฟล์และไฟล์อื่น ๆ ดาวน์โหลดล้มเหลว (เฉพาะไฟล์ขนาดใหญ่ 100 MB แรก) ซึ่งฉันสงสัยว่าเป็นไฟล์เดียวกัน

ในการตรวจสอบสิ่งนี้ฉันต้องการตรวจสอบแฮชของพวกเขา แต่เนื่องจากฉันมีเพียงบางส่วนของไฟล์ที่ดาวน์โหลดไม่สำเร็จฉันต้องการแฮชเพียงไม่กี่เมกะไบต์แรกหรือมากกว่านั้น

ฉันจะทำสิ่งนี้ได้อย่างไร

ระบบปฏิบัติการจะเป็น windows แต่ฉันติดตั้ง cygwin และ MinGW แล้ว


1
การเปรียบเทียบไฟล์หนึ่งไฟล์บนเครื่องคอมพิวเตอร์กับไฟล์อื่นบนคอมพิวเตอร์ที่อยู่ห่างไกลเป็นส่วนสำคัญของrsyncซึ่งเปรียบเทียบส่วนต่าง ๆ ของไฟล์ด้วยฟังก์ชันแฮชพิเศษ
เดวิดแครี

@DavidCary ในกรณีของฉันฉันไม่มีสิทธิ์เข้าถึงเชลล์ในคอมพิวเตอร์ระยะไกล แต่ขอบคุณสำหรับคำใบ้ฉันจะอ่าน manpage
ทำบาป

คำตอบ:


56

การสร้างแฮชเพื่อเปรียบเทียบไฟล์นั้นสมเหตุสมผลถ้าคุณเปรียบเทียบไฟล์หนึ่งไฟล์กับไฟล์หลายไฟล์หรือเมื่อเปรียบเทียบไฟล์หลายไฟล์กับอีกไฟล์หนึ่ง

มันไม่สมเหตุสมผลเมื่อเปรียบเทียบสองไฟล์เพียงครั้งเดียว: ความพยายามในการคำนวณแฮชอย่างน้อยก็สูงเท่ากับการเดินข้ามไฟล์และทำการเปรียบเทียบโดยตรง

เครื่องมือเปรียบเทียบไฟล์ที่มีประสิทธิภาพคือcmp:

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

คุณสามารถรวมเข้าด้วยกันddเพื่อเปรียบเทียบส่วนต่าง ๆ (ไม่จำเป็นตั้งแต่ต้น) ของสองไฟล์เช่น:

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
หมายเหตุ: การสร้างแฮชเพื่อเปรียบเทียบไฟล์ยังมีเหตุผลถ้าคุณต้องการหลีกเลี่ยงการอ่านสองไฟล์ในเวลาเดียวกัน
Kamil Maciorowski

1
@KamilMaciorowski ใช่จริง แต่วิธีนี้จะยังเร็วกว่าการเปรียบเทียบแฮชในกรณีที่เป็นแบบคู่
Konrad Rudolph

8
นี่คือทางออกที่ต้องไป cmpมีความแน่นอน 99.99% ที่จะติดตั้งไว้แล้วหากคุณbashใช้งานและทำงานได้ แน่นอนว่าcmp -n 131072 one.zip two.zip จะทำงานเช่นกัน อักขระที่พิมพ์น้อยและการดำเนินการที่เร็วที่สุด การคำนวณแฮชเป็นเรื่องไร้สาระ มันต้องอ่านไฟล์ 100MB ทั้งหมดรวมทั้งส่วน 100MB ของไฟล์สมบูรณ์ซึ่งไม่มีจุดหมาย หากเป็นไฟล์ zip และแตกต่างกันจะมีความแตกต่างกันในช่วงสองสามร้อยไบต์แรก Readahead มอบความจุ 128k เป็นค่าเริ่มต้นดังนั้นคุณสามารถเปรียบเทียบ 128k (ราคาเดียวกับการเปรียบเทียบ 1 ไบต์)
Damon

19
--bytesตัวเลือกเพียงแทรกซ้อนงาน เพียงแค่รันcmpโดยไม่มีตัวเลือกนี้และมันจะแสดงไบต์แรกที่แตกต่างระหว่างไฟล์ หากไบต์ทั้งหมดเท่ากันก็จะแสดงEOFไฟล์ที่สั้นกว่า สิ่งนี้จะให้ข้อมูลมากกว่าตัวอย่างของคุณ - มีจำนวนไบต์ที่ถูกต้อง
pabouk

2
ถ้าคุณมี GNU cmp(และผมคิดว่าทุกคนสวยมากไม่) คุณสามารถใช้--ignore-initialและข้อโต้แย้งแทนแทรกซ้อนสิ่งที่มีสวดของ--bytes dd
Christopher Schultz

12

ฉันขอโทษฉันไม่สามารถลองได้ แต่วิธีนี้จะได้ผล

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

นี่จะเป็น 100 เมกะไบต์แรกของทั้งสองไฟล์

ตอนนี้รับแฮช:

sha256sum first100mb1.dat && sha256sum first100mb2.dat 

คุณสามารถเรียกใช้โดยตรง:

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

1
มีวิธีการไพพ์ dd อย่างใดใน sha256sum โดยไม่มีไฟล์กลางหรือไม่?
ทำบาป

1
ฉันได้เพิ่มวิธีอื่นตามคำขอของคุณ
davidbaumann

8
ทำไมต้องสร้างแฮช มันมีประสิทธิภาพน้อยกว่าการเปรียบเทียบแฟรกเมนต์ไฟล์โดยตรง (โดยใช้cmp)
Konrad Rudolph

ในตัวอย่างรหัสกลางของคุณคุณบอกว่า first100mb1.dat สองครั้ง คุณหมายถึง first100mb 2 .dat สำหรับอันที่สองใช่ไหม
doppelgreener

@ KonradRudolph "ทำไมต้องสร้างแฮช" โซลูชันของคุณ (โดยใช้cmp) เป็นผู้ชนะอย่างไม่ต้องสงสัย แต่วิธีนี้ในการแก้ปัญหา (ใช้แฮช) ก็มีสิทธิ์ที่จะมีอยู่ตราบใดที่มันแก้ปัญหาได้จริง (:
VL-80

7

ดูเหมือนว่าทุกคนจะไปเส้นทาง Unix / Linux ด้วยวิธีนี้ แต่การเปรียบเทียบ 2 ไฟล์สามารถทำได้อย่างง่ายดายด้วยคำสั่งมาตรฐานของ Windows:
FC /B file file2

FC มีอยู่ใน Windows NT ทุกรุ่นที่เคยมีมา และ (ถ้าฉันจำได้ถูกต้อง) ก็มีอยู่ในดอส
มันค่อนข้างช้า แต่ไม่สำคัญว่าจะใช้เพียงครั้งเดียว


6

คุณสามารถเพียงโดยตรงเปรียบเทียบไฟล์ที่มีโปรแกรมไบนารี / hex vbindiffต่างเช่น มันเปรียบเทียบไฟล์อย่างรวดเร็วสูงสุด 4GB บน Linux และ Windows

มีลักษณะเช่นนี้เฉพาะกับความแตกต่างที่เน้นด้วยสีแดง (1B กับ 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     
└──────────────────────────────────────────────────────────────────────────────┘ 

ในกรณีของฉันไฟล์เป็นไฟล์เก็บถาวร zip ดังนั้นจึงไม่มีข้อความที่มีความหมายอยู่ในนั้น การเปรียบเทียบค่าแฮชควรเร็วขึ้นและมีข้อผิดพลาดน้อยลง
ทำบาป

2
หากคุณหมายถึงข้อความ ASCII แสดงว่าไม่เกี่ยวข้อง vbindiff(และ Konrad's cmp) เปรียบเทียบข้อมูลไบนารีไบต์สำหรับไบต์ ในความเป็นจริงมีค่ามีแนวโน้มมากขึ้นที่จะได้สัมผัสกับการชน
Xen2050

* หมายถึง "อันที่จริงค่าแฮชมีแนวโน้มที่จะประสบกับการชน" ในความคิดเห็นด้านบนพลาด h!
Xen2050

0

ฉันรู้ว่ามันบอกว่าสำหรับ Bash แต่ OP ก็ระบุว่าพวกเขามี Windows สำหรับทุกคนที่ต้องการ / ต้องการโซลูชัน Windows มีโปรแกรมชื่อ HxD ซึ่งเป็นตัวแก้ไข Hex ที่สามารถเปรียบเทียบสองไฟล์ได้ หากไฟล์มีขนาดแตกต่างกันมันจะบอกว่าชิ้นส่วนที่มีอยู่เหมือนกันหรือไม่ และถ้าจำเป็นก็สามารถเรียกใช้ checksums สำหรับสิ่งที่เลือกไว้ในปัจจุบัน ได้ฟรีและสามารถดาวน์โหลดได้จาก: เว็บไซต์ HxD ฉันไม่มีความเกี่ยวข้องใด ๆ กับผู้แต่งฉันเพิ่งใช้มาหลายปีแล้ว


0

cmp จะบอกคุณเมื่อไฟล์สองไฟล์เหมือนกันจนถึงความยาวของไฟล์ขนาดเล็ก:

$ 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 กำลังบอกคุณว่าการเปรียบเทียบพบ EOF ในไฟล์ a ก่อนที่จะตรวจพบความแตกต่างระหว่างสองไฟล์


จุดดี. หากคุณไม่ได้เห็นนี่เป็นสิ่งที่ pabouk แสดงความคิดเห็นในคำตอบที่ยอมรับแล้ว
ทำผิด
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.