İki sıkıştırılmış dosyanın eşit olup olmadığını nasıl kontrol edebilirim?


11

Ben sadece bir metin dosyasına veri dökerek "aptal" yedekleme yaparken yerden tasarruf çalışıyorum. Yedek komut dosyam günlük olarak yürütülür ve şöyle görünür:

  1. Yedekleme tarihinden sonra bir dizin oluşturun.
  2. Bazı verileri bir metin dosyasına dökün "$name".
  3. Dosya geçerliyse, bunu gziplemek: gzip "$name". Aksi takdirde rm "$name".

Şimdi, aynı veriler önceki gün de mevcutsa (ve symlink veya hardlink oluştur) bir dosyayı kaldırmak için ek bir adım eklemek istiyorum.

İlk başta kullanmayı düşündüm md5sum "$name", ancak bu işe yaramıyor çünkü dosya adını ve oluşturulma tarihini de saklıyorum.

gzipİki sıkıştırılmış dosyayı karşılaştırma ve bana eşit olup olmadıklarını söyleme seçeneği var mı ? Eğer gzipböyle bir seçenek yok, benim hedefe ulaşmak için başka bir yol var mı?



2
Ben önerecektim diff <(zcat file1) <(zcat file2), ama mrethub'ın önerisi zdiffçok daha iyi görünüyor.
Kevin

backuppc , manuel olarak elde etmeye çalıştığınız şeyi sizin için yapar
drone.ah

günde sadece bir dosya varsa @ drohne.ah Backuppc (Ben bir gzip için duygusunun çok yapar bir SQL dökümü gibi 's sth tahmin) ... tür bir overkill olabilir
mreithub

1
@mdpc MD5'teki algoritma sorunları muhtemelen ilgili değildir. Çarpışmalar inşa etmek mümkündür, ancak muhtemelen tek endişe, bir saldırgan tarafından değil, tesadüfen meydana gelenlerdir. Ve ~ 2 ^ 64 dosyalarınız olana kadar bunun gerçekleşmesi pek olası değildir. Preimage atak bile önemli değil.
derobert

Yanıtlar:


7

Yorumunda mreithub'ın önerdiği gibi zcmpveya kullanabilirsiniz zdiff(veya benzer Kevin komutunu). Bunlar, her iki dosyayı cmpda açıp daha sonra veya 'a ilettikleri için nispeten verimsiz olacaktır diff. Eğer sadece "aynı mıdırlar" diye cevaplamak istiyorsanız cmp, çok daha hızlı olacaktır.

İle yaklaşımınız md5summükemmel, ancak çalıştırmadan önce MD5'i almanız gerekiyor gzip. Ardından, ortaya çıkan .gzdosyanın yanındaki bir dosyada saklayın . Daha sonra sıkıştırmadan önce dosyayı kolayca karşılaştırabilirsiniz. İsim aynıysa, md5sum -cbunu sizin için yapar.

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

Ve bir sonraki yedekleme:

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

Yani değişmedi. OTOH, değişmiş olsaydı:

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

Eğer geçerseniz --quiet, size sadece çıkış kodunu verecektir. Eşleşen için 0, farklı için 0 olmayan.

MD5 oldukça hızlı, ama çok da öyle değil. MD4 ( openssl md4komut satırında elde ettiğiniz en iyi şeydir, sanırım) yaklaşık iki kat daha hızlıdır (ne ne de MD5 güvenlidir, ancak ikisi de onları yıkmaya çalışmadığında çarpışmalara karşı dayanıklıdır). SHA-1 ( sha1sum) daha güvenli, ancak daha yavaş; SHA-256 ( sha256sum) güvenlidir, ancak daha da yavaştır. CRC32 çok daha hızlı olmalı, ancak daha kısadır ve bu nedenle daha rastgele çarpışmalara sahip olacaktır. Aynı zamanda tamamen güvensiz.


zdiffSadece bilmek istediğimiz gibi kaybi olsun bir dosya değil, değişti neyi . zcmpilginç görünüyor, bunu deneyeceğim.
Lekensteyn

7

@ derobert'in cevabı harika, ancak bulduğum bazı bilgileri paylaşmak istiyorum.

gzip -l -v

gzip sıkıştırılmış dosyalar zaten bir karma içerir (ancak güvenli değil, bu SO yazısına bakın ):

$ 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

Hızlı bir parmak izi elde etmek için CRC ve sıkıştırılmamış boyut birleştirilebilir:

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

cmp

İki baytın eşit olup olmadığını kontrol etmek için kullanın cmp file1 file2. Şimdi, gzip ile sıkıştırılmış bir dosyaya veri ve altbilgi (CRC artı orijinal boyut) eklenmiş bir başlık var. Gzip biçimi tanımı başlık dosyası sıkıştırılmıştır ve dosya ismi 10-bayt başlığından sonra eklenen bir nul-sonlu dizisi olduğu zaman içerdiğini gösterir.

Bu nedenle, dosya adının sabit olduğunu ve aynı command ( gzip "$name") kullanıldığını varsayarsak cmp, zaman dahil ilk baytları kullanarak ve atlayarak iki dosyanın farklı olup olmadığını kontrol edebiliriz :

cmp -i 8 file1 file2

Not : aynı sıkıştırma seçeneklerinin önemli olduğu varsayımı, aksi takdirde komut her zaman dosyayı farklı olarak rapor edecektir. Bunun nedeni, sıkıştırma seçeneklerinin başlıkta depolanması ve sıkıştırılmış verileri etkileyebilmesidir. cmpsadece ham baytlara bakar ve bunu gzip olarak yorumlamaz.

Aynı uzunlukta dosya adlarınız varsa, dosya adını okuduktan sonra atlanacak baytları hesaplamayı deneyebilirsiniz. Dosya adları farklı boyutlarda olduğunda, cmpbaytları atladıktan sonra çalışabilirsiniz cmp <(cut -b9- file1) <(cut -b10- file2).

zcmp

Bu kesinlikle gitmek için en iyi yoldur, önce verileri sıkıştırır ve baytları karşılaştırmaya başlar cmp(gerçekten, zcmp( zdiff) shellscriptinde yapılan budur).

Bir not, kılavuz sayfasında aşağıdaki nottan korkmayın:

Karşılaştırma işleminden önce her iki dosyanın da sıkıştırılması gerektiğinde, ikincisi / tmp ile sıkıştırılmamış olur. Diğer tüm durumlarda, zdiff ve zcmp yalnızca bir boru kullanır.

Yeterince yeni bir Bash'iniz olduğunda, sıkıştırma geçici bir dosya kullanmaz, sadece bir pipo kullanır. Veya, zdiffkaynağın dediği gibi:

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

Bayt 4 (FLG) 0 ise, dosya adı başlıkta değildir, bu nedenle uzunluğu hakkında endişelenmenize gerek yoktur. Ayrıca, gzip -v -lbaşlıktaki dört MTIME baytı sıfırsa, MTIME yerine dosya zamanını bildireceğini buldum . Ayrıca MTIME varsa, sıkıştırma işleminin başladığı zaman dosya zamanından biraz önce olduğuna dikkat edin.
kitchin

0

İki gzip dosyasını karşılaştırmak için, sadece içerik, bir komut, hayır diff, sadece karşılaştırmamd5sum

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

İlgili farklılıklar için "filtreleyebilirsiniz",

$ 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

Komut dosyası oluşturuyorsa, bir filtre işlevi öneririm (test edilmedi, sadece bir örnek),

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 bir atıktır, kullanabilirsiniz cmp. zcatve grepbirleştirilebilir zgrep.
Lekensteyn

doğru, md5sum'u karşılaştırmak gerekli değildir (zaten oluşturmamışsanız); Derobert kullandığından beri kullandım. zgrep, temelde gunzip ve grep (veya duruma göre sed) yapan bir betiktir, bu yüzden orada çok az fark vardır. yayınlandığı gibi komut dosyası kasıtlı olarak takılabilir parçalara sahip bir boru zinciri olarak gösterilir; her şeyi tek bir komuta dönüştürmenin eğlenceli yanı nedir?
michael

1
Ve zcatsadece gunzip -c. Doğru iş için doğru aleti kullanın, KISS şişkinlikten daha iyidir. Bu durumda, zamanımı gerektiğinde sabit bağlantılar oluşturan bir şey yazmaya harcıyorum, bu daha eğlenceli.
Lekensteyn
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.