ฉันจะตรวจสอบว่าไฟล์ gzipped สองไฟล์เท่ากันได้อย่างไร


11

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

  1. สร้างไดเรกทอรีชื่อหลังจากวันที่สำรองข้อมูล
  2. "$name"การถ่ายโอนข้อมูลข้อมูลบางอย่างลงในแฟ้มข้อความ
  3. ถ้าแฟ้มถูกต้อง gzip gzip "$name"มัน มิฉะนั้น, rm "$name".

ตอนนี้ฉันต้องการเพิ่มขั้นตอนเพิ่มเติมเพื่อลบไฟล์หากมีข้อมูลเดียวกันในวันก่อน (และสร้าง symlink หรือ hardlink)

ตอนแรกฉันคิดว่าจะใช้md5sum "$name"แต่สิ่งนี้ไม่ได้ผลเพราะฉันยังเก็บชื่อไฟล์และวันที่สร้าง

ไม่gzipได้มีตัวเลือกที่จะเปรียบเทียบสองไฟล์ gzipped และบอกฉันว่าพวกเขามีค่าเท่ากันหรือไม่? หากgzipไม่มีตัวเลือกดังกล่าวจะมีวิธีอื่นในการบรรลุเป้าหมายของฉันหรือไม่


1
ลองนี้: linux.die.net/man/1/zdiff
mreithub

2
ฉันจะแนะนำdiff <(zcat file1) <(zcat file2)แต่คำแนะนำของ mrethub เกี่ยวกับการzdiffดูดีขึ้นมาก
เควิน

backuppcทำเพื่อคุณในสิ่งที่คุณพยายามทำด้วยตนเอง
drone.ah

@ drohne.ah backuppc อาจจะมีชนิดของ overkill ถ้ามันเป็นเพียงหนึ่งไฟล์ต่อวัน ... (ฉันเดามันฏเหมือนการถ่ายโอนข้อมูล SQL ที่มันทำให้จำนวนมากที่มีความรู้สึกที่จะ gzip)
mreithub

1
@mdpc ปัญหาอัลกอริทึมใน MD5 อาจไม่เกี่ยวข้องกัน เป็นไปได้ที่จะสร้างการชน แต่น่าจะเป็นปัญหาเดียวที่เกิดขึ้นโดยบังเอิญไม่ใช่โดยผู้โจมตี และยังไม่เกิดขึ้นจนกว่าคุณจะมีไฟล์ ~ 2 ^ 64 แม้แต่การโจมตีแบบ preimage ก็ไม่สำคัญ
Derobert

คำตอบ:


7

คุณสามารถใช้zcmpหรือzdiffตาม mreithub แนะนำในความคิดเห็นของเขา (หรือคำสั่งของเควินซึ่งคล้ายกัน) เหล่านี้จะค่อนข้างไม่มีประสิทธิภาพตามความเป็นจริงทั้งขยายขนาดไฟล์แล้วผ่านพวกเขาออกไปหรือcmp diffหากคุณเพียงแค่ต้องการตอบว่า "พวกเขาเหมือนกัน" คุณต้องการcmpมันจะเร็วขึ้นมาก

วิธีการของคุณกับmd5sumเป็นสิ่งที่ดีอย่างสมบูรณ์แบบ แต่คุณจำเป็นต้องใช้ MD5 ก่อนที่จะgzipทำงาน จากนั้นเก็บไว้ในไฟล์พร้อมกับ.gzไฟล์ผลลัพธ์ คุณสามารถเปรียบเทียบไฟล์ได้ง่าย ๆ ก่อนทำการบีบอัด หากชื่อเหมือนกันmd5sum -cจะทำเพื่อคุณ

$ mkdir "backup1"
$ cd backup1
$ echo "test" > backup-file
$ md5sum backup-file > backup-file.md5
$ gzip -9 backup-file

และการสำรองข้อมูลต่อไป:

$ mkdir "backup2"
$ cd backup2
$ echo "test" > backup-file
$ md5sum -c ../backup1/backup-file.md5 
backup-file: OK

ดังนั้นมันจึงไม่เปลี่ยนแปลง OTOH ถ้ามันเปลี่ยน:

$ echo "different" > backup-file
$ md5sum -c ../backup1/backup-file.md5 
backup-file: FAILED
md5sum: WARNING: 1 computed checksum did NOT match

หากคุณผ่าน--quietไปมันจะให้รหัสทางออก 0 สำหรับการจับคู่ไม่ใช่สำหรับ 0 แตกต่างกัน

MD5 นั้นค่อนข้างเร็ว แต่ก็ไม่เด่นนัก MD4 ( openssl md4เป็นสิ่งที่ดีที่สุดที่คุณได้รับจากบรรทัดคำสั่งฉันเชื่อว่า) เร็วกว่าสองเท่า (ไม่ใช่ทั้งสองอย่างและไม่ปลอดภัยสำหรับ MD5 แต่ทั้งคู่มีความทนทานต่อการชนกันมาก SHA-1 ( sha1sum) มีความปลอดภัยมากขึ้น แต่ช้า; SHA-256 ( sha256sum) ปลอดภัย แต่ก็ยังช้ากว่า CRC32 ควรเร็วขึ้นหลายเท่า แต่จะสั้นกว่าและจะมีการชนแบบสุ่มมากขึ้น มันยังไม่ปลอดภัยอย่างสิ้นเชิง


zdiffดูเหมือนว่าเสียเป็นผมแค่อยากจะรู้ว่าไม่ว่าจะเป็นไฟล์ที่มีการเปลี่ยนแปลงไม่ว่าอะไร zcmpดูน่าสนใจฉันจะลองดู
Lekensteyn

7

คำตอบของ@derobertนั้นยอดเยี่ยมถึงแม้ว่าฉันต้องการแบ่งปันข้อมูลอื่น ๆ ที่ฉันได้พบ

gzip -l -v

ไฟล์บีบอัด gzip มีแฮชอยู่แล้ว (ไม่ปลอดภัยดูที่โพสต์ SO ):

$ echo something > foo
$ gzip foo
$ gzip -v -l foo.gz 
method  crc     date  time           compressed        uncompressed  ratio uncompressed_name
defla 18b1f736 Feb  8 22:34                  34                  10 -20.0% foo

หนึ่งสามารถรวม CRC และขนาดที่ไม่บีบอัดเพื่อให้ได้ลายนิ้วมือที่รวดเร็ว:

gzip -v -l foo.gz | awk '{print $2, $7}'

CMP

cmp file1 file2สำหรับการตรวจสอบว่าไบต์ที่สองมีค่าเท่ากันหรือไม่ใช้ ตอนนี้ไฟล์ gzipped มีส่วนหัวที่มีข้อมูลและส่วนท้าย (CRC บวกขนาดดั้งเดิม) ต่อท้าย รายละเอียดของรูปแบบ gzipแสดงให้เห็นว่าส่วนหัวมีเวลาเมื่อไฟล์ถูกบีบอัดและว่าชื่อแฟ้มเป็นสตริง NUL สิ้นสุดที่ถูกผนวกหลังจากที่ส่วนหัว 10 ไบต์

ดังนั้นสมมติว่าชื่อไฟล์คงที่และใช้คำสั่งเดียวกัน ( gzip "$name") สามารถตรวจสอบว่าไฟล์สองไฟล์แตกต่างกันหรือไม่โดยใช้cmpและข้ามไบต์แรกรวมถึงเวลา:

cmp -i 8 file1 file2

หมายเหตุ : ข้อสันนิษฐานว่าตัวเลือกการบีบอัดข้อมูลเดียวกันมีความสำคัญมิฉะนั้นคำสั่งจะรายงานไฟล์ที่แตกต่างเสมอ สิ่งนี้เกิดขึ้นเนื่องจากตัวเลือกการบีบอัดถูกเก็บไว้ในส่วนหัวและอาจส่งผลต่อข้อมูลที่บีบอัด cmpเพียงแค่ดูที่ไบต์ดิบและไม่ตีความว่าเป็น gzip

หากคุณมีชื่อไฟล์ที่มีความยาวเท่ากันคุณสามารถลองคำนวณจำนวนไบต์ที่จะข้ามไปหลังจากอ่านชื่อไฟล์ เมื่อชื่อไฟล์ที่มีขนาดแตกต่างกันคุณสามารถเรียกใช้หลังจากข้ามไบต์เช่นcmpcmp <(cut -b9- file1) <(cut -b10- file2)

zcmp

นี่เป็นวิธีที่ดีที่สุดที่จะไปแน่นอนมันบีบอัดข้อมูลและเริ่มเปรียบเทียบไบต์ด้วยcmp(จริงๆนี่คือสิ่งที่ทำในzcmp( zdiff) shellscript)

One note, อย่ากลัวหมายเหตุต่อไปนี้ในหน้าคู่มือ:

เมื่อไฟล์ทั้งสองต้องไม่ถูกบีบอัดก่อนทำการเปรียบเทียบไฟล์ที่สองจะไม่ถูกบีบอัดเป็น / tmp ในกรณีอื่น ๆ ทั้งหมด zdiff และ zcmp ใช้ไปป์เท่านั้น

เมื่อคุณมี Bash ใหม่อย่างเพียงพอการบีบอัดจะไม่ใช้ไฟล์ชั่วคราวเพียงแค่ไปป์ หรืออย่างที่zdiffบอกว่า:

# Reject Solaris 8's buggy /bin/bash 2.03.

หาก byte 4 (FLG) เป็น 0 ดังนั้นชื่อไฟล์ไม่ได้อยู่ในส่วนหัวดังนั้นคุณไม่จำเป็นต้องกังวลเกี่ยวกับความยาว นอกจากนี้ฉันพบว่าgzip -v -lจะรายงานเวลาไฟล์แทน MTIME หากสี่ไบต์ MTIME ในส่วนหัวเป็นศูนย์ โปรดทราบด้วยว่า MTIME อยู่ที่นั่นหรือไม่โดยทั่วไปจะเป็นเวลาก่อนเวลาไฟล์เพราะเมื่อการบีบอัดเริ่มต้น
kitchin

0

หากต้องการเปรียบเทียบสองไฟล์ gzip เพียงแค่เนื้อหาหนึ่งคำสั่งไม่diffเพียงเปรียบเทียบmd5sum

$ diff -q <(zcat one.gz|md5sum|cut -f1 -d' ') \
          <(zcat two.gz|md5sum|cut -f1 -d' ') \
    && echo same || echo not_same

นอกจากนี้คุณยังสามารถ "กรอง" สำหรับความแตกต่างที่เกี่ยวข้อง

$ diff -q <(zcat one.gz|grep -v '^-- Dump completed'|md5sum|cut -f1 -d' ') \
          <(zcat two.gz|grep -v '^-- Dump completed'|md5sum|cut -f1 -d' ') \
   && echo same || echo not_same

หากการเขียนสคริปต์ฉันขอแนะนำฟังก์ชั่นตัวกรอง (ไม่ได้ทดสอบเพียงตัวอย่าง)

do_filter_sum() {
  zcat $1 | grep -v '^-- Dump completed' | md5sum | cut -f1 -d' '
}

diff -q <(do_filter_sum one.gz) \
        <(do_filter_sum two.gz) \
        && echo same || echo not_same

md5sum เป็นของเสียที่คุณสามารถcmpใช้ได้ zcatและgrepสามารถผสานเข้าzgrepกับ
Lekensteyn

จริง md5sum ไม่จำเป็นต้องเปรียบเทียบ (เว้นแต่คุณจะสร้างมันขึ้นมาแล้ว); ฉันเพิ่งใช้มันตั้งแต่ Derobert ใช้มัน zgrep เป็นเพียงสคริปต์ที่ทำกันโดยทั่วไปคือ gunzip และ grep (หรืออาจเป็นเพราะกรณี) ดังนั้นจึงมีความแตกต่างเล็กน้อย สคริปต์ที่โพสต์นั้นแสดงให้เห็นอย่างตั้งใจว่าเป็นโซ่ของท่อที่มีชิ้นส่วนที่เสียบได้ ความสนุกในการรวมทุกอย่างลงในคำสั่งเดียวคืออะไร?
ไมเคิล

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