Bir dizinin md5 sağlama toplamını nasıl hesaplayabilirim?


133

*.pyBir dizinin ve tüm alt dizinlerin altına yerleştirilmiş belirli bir türdeki ( örneğin) tüm dosyalar için bir özet md5 sağlama toplamı hesaplamam gerekiyor .

Bunu yapmanın en iyi yolu nedir?

Düzenleme: Önerilen çözümler çok güzel, ancak bu tam olarak ihtiyacım olan şey değil. Dizini bir bütün olarak benzersiz şekilde tanımlayacak tek bir özet sağlama toplamı elde etmek için bir çözüm arıyorum - tüm alt dizinlerinin içeriği dahil.


Daha ayrıntılı bir açıklama için buna ve buna bir göz atın .
luvieere

3
Bana bir süper kullanıcı sorusu gibi görünüyor.
Noldorin

8
Sağlama toplamlarının hiçbir şeyi benzersiz şekilde tanımlamadığını unutmayın .
Hosam Aly

1
Neden benzersiz bir şekilde tanımlamak istediğiniz "aynı" olabilecek veya olmayabilecek iki dizin ağacınız olsun ki? Dosya oluşturma / değiştirme / erişim zamanı önemli mi? Gerçekten ihtiyacınız olan şey sürüm kontrolü mü?
jmucchiello

Benim durumumda gerçekten önemli olan, tüm dizin ağacı içeriğinin benzerliğidir, bu da AFAIK anlamına gelir: 1) dizin ağacının altındaki herhangi bir dosyanın içeriği değiştirilmedi 2) dizin ağacına yeni dosya eklenmedi 3) dosya yok silindi
victorz

Yanıtlar:


152
find /path/to/dir/ -type f -name "*.py" -exec md5sum {} + | awk '{print $1}' | sort | md5sum

Find komutu .py ile biten tüm dosyaları listeler. Md5sum, her .py dosyası için hesaplanır. awk, md5 toplamlarını seçmek için kullanılır (benzersiz olmayabilecek dosya adlarını göz ardı ederek). Md5sum'lar sıralanır. Bu sıralı listenin md5sum'u daha sonra döndürülür.

Bunu bir test dizini kopyalayarak test ettim:

rsync -a ~/pybin/ ~/pybin2/

~ / Pybin2 içindeki bazı dosyaları yeniden adlandırdım.

find...md5sumKomut hem dizinler için aynı çıktıyı verir.

2bcf49a4d19ef9abd284311108d626f1  -

24
Bir dosya yeniden adlandırılırsa aynı sağlama toplamının oluşturulacağını unutmayın. İmzanın dosya düzenini düşünürseniz, bu "dizini bir bütün olarak benzersiz bir şekilde tanımlayacak bir sağlama toplamına" tam olarak uymaz.
Valentin Milea

1
Her dosya sağlama toplamının önüne dosyanın adını (veya daha da iyisi, dosyanın / yol / dan / dir / dizinine göreceli yolunu) eklemek için komut satırını biraz değiştirebilirsiniz, böylece son sağlama toplamında dikkate alınır.
Michael Zilbermann

4
@ zim2001: Evet, değiştirilebilir, ancak problemi anladığım için (özellikle OP'nin soru altındaki yorumu nedeniyle) OP , dosyaların içeriği dosya adı veya eşit bağıl yol.
unutbu

@unutbu: Biliyorum; Valentin Milea'dan bir önceki nota tepki veriyordum.
Michael Zilbermann

@ValentinMilea, awk ...düzeni imzanın bir parçası olarak görüyorsanız, yalnızca parçayı kaldırın .
segfault

166

Anında bir tar arşiv dosyası oluşturun ve bunu şu şekilde yönlendirin md5sum:

tar c dir | md5sum

Bu, dosyanız ve alt dizin kurulumunuz için benzersiz olması gereken tek bir md5sum üretir. Diskte dosya oluşturulmaz.


25
@CharlesB tek bir kontrol toplamıyla hangi dosyanın farklı olduğunu asla bilemezsiniz. Soru, bir dizin için tek bir kontrol toplamı hakkındaydı.
Hawken

17
ls -alR dir | md5sum. Bu daha da iyi sıkıştırma yok, sadece okuma. Benzersizdir çünkü içerik, dosyanın mod zamanını ve boyutunu içerir;)
Sid

14
@ Daps0l - komutumda sıkıştırma yok. zGzip veya jbzip2 için eklemeniz gerekir . Ben de yapmadım.
ire_and_curses

7
Bunu yapmanın, yalnızca dosyaların içeriğini değil, sağlama toplamı hesaplamasındaki dosyaların ve diğer şeylerin zaman damgasını da entegre edeceğine dikkat edin
Michael Zilbermann

10
Bu çok hoş, ama gerçekten işe yaramıyor. tarAynı dosya kümesini iki kez veya iki farklı bilgisayarda kullanmanın aynı sonucu vereceğinin garantisi yoktur .
fletom

46

ire_and_curses'in kullanma önerisinde tar c <dir>bazı sorunlar var:

  • tar, dizin girdilerini dosya sisteminde saklandıkları sırayla işler ve bu sırayı değiştirmenin bir yolu yoktur. Farklı yerlerde "aynı" dizine sahipseniz ve bunu düzeltmenin bir yolunu bilmiyorum (tar, girdi dosyalarını belirli bir sırayla "sıralayamaz").
  • Genelde groupid ve ownerid numaralarının aynı olup olmadığı ile ilgilenirim, grup / sahibin dize gösteriminin aynı olup olmadığı gerekmez. Bu, örneğin rsync -a --deleteyaptığı şeyle aynı doğrultudadır : hemen hemen her şeyi (eksi xattrs ve acls) senkronize eder, ancak sahibi ve grubu dizgi temsiline göre değil, kimliklerine göre senkronize eder. Dolayısıyla, aynı kullanıcılara / gruplara sahip olması gerekmeyen farklı bir sistemle senkronize ettiyseniz, --numeric-ownerbayrağı tar'a eklemelisiniz.
  • tar, kendisini kontrol ettiğiniz dizinin dosya adını içerecektir, sadece dikkat edilmesi gereken bir şey.

İlk sorun için herhangi bir çözüm bulunmadığı sürece (veya bunun sizi etkilemeyeceğinden emin olmadığınız sürece), bu yaklaşımı kullanmam.

findOnlar sadece checksumming zihni boş dizinleri tutmalı eğer bir sorun haline gelir dosyaları değil dizinleri içerir çünkü yukarıda önerilen tabanlı çözümler de hiç iyi.

Son olarak, önerilen çözümlerin çoğu tutarlı bir şekilde sıralanmaz, çünkü harmanlama sistemler arasında farklı olabilir.

Bulduğum çözüm bu:

dir=<mydir>; (find "$dir" -type f -exec md5sum {} +; find "$dir" -type d) | LC_ALL=C sort | md5sum

Bu çözümle ilgili notlar:

  • LC_ALL=CSistemleri arasında güvenilir bir sıralama düzeni sağlamaktır
  • Bu, "satırla \ nadlı" bir dizin ile "adı" ve "satırla" olan iki dizin arasında ayrım yapmaz, ancak bunun gerçekleşme olasılığı çok düşük görünüyor. Biri bunu genellikle bir -print0bayrakla düzeltir , findancak burada başka şeyler olduğu için, yalnızca komutu daha karmaşık hale getirecek çözümleri görebiliyorum, buna değer.

Not: Sistemlerimden biri, finddesteklemeyen -execveya -print0işaretlemeyen sınırlı bir meşgul kutusu kullanıyor ve ayrıca dizinleri belirtmek için "/" ekliyor, ancak findutils bulamıyor gibi görünüyor, bu nedenle bu makine için çalıştırmam gerekiyor:

dir=<mydir>; (find "$dir" -type f | while read f; do md5sum "$f"; done; find "$dir" -type d | sed 's#/$##') | LC_ALL=C sort | md5sum

Şans eseri, adlarında satırsonu olan dosya / dizin yok, bu yüzden bu sistemde bir sorun değil.


1
+1: Çok ilginç! Sıranın farklı dosya sistemi türleri arasında veya aynı dosya sistemi içinde farklılık gösterebileceğini mi söylüyorsunuz?
ire_and_curses

2
her ikisi de. sadece her dizindeki dizin girişlerinin sırasına bağlıdır. AFAIK dizin girişleri (dosya sisteminde) sadece "dizinde dosya oluşturduğunuz" sırayla oluşturulur. Basit bir örnek: $ mkdir a; a / dosya-1'e dokunun; a / file-2'ye dokunun $ mkdir b; b / dosya-2'ye dokunun; b / file-1 $ 'a dokunun (cd a; tar -c. | md5sum) fb29e7af140aeea5a2647974f7cdec77 - $ (cd b; tar -c. | md5sum) a3a39358158a87059b9f111ccffa1023 -
Dieter_be

15

Yalnızca dosyaları önemsiyorsanız ve boş dizinleri değil, bu işe yarar:

find /path -type f | sort -u | xargs cat | md5sum


9

Benim için en çok işe yarayan çözüm:

find "$path" -type f -print0 | sort -z | xargs -r0 md5sum | md5sum

Benim için en iyi sonuç vermesinin nedeni:

  1. boşluk içeren dosya adlarını işler
  2. Dosya sistemi meta verilerini yok sayar
  3. Dosyanın yeniden adlandırılıp adlandırılmadığını algılar

Diğer cevaplarla ilgili sorunlar:

Dosya sistemi meta verileri aşağıdakiler için göz ardı edilmez:

tar c - "$path" | md5sum

Boşluk içeren dosya adlarını işlemez veya dosyanın yeniden adlandırılıp adlandırılmadığını algılamaz:

find /path -type f | sort -u | xargs cat | md5sum

4

Tüm dizini kapsayan bir md5sum istiyorsanız, şöyle bir şey yapacağım

cat *.py | md5sum 

1
Alt dizinler için cat **.py| md5sum
Ramon

3

Hem içerik hem de dosya adları dahil tüm dosyaları sağlama toplamı

grep -ar -e . /your/dir | md5sum | cut -c-32

Yukarıdakiyle aynı, ancak yalnızca * .py dosyaları dahil

grep -ar -e . --include="*.py" /your/dir | md5sum | cut -c-32

İsterseniz sembolik bağlantıları da takip edebilirsiniz

grep -aR -e . /your/dir | md5sum | cut -c-32

Grep ile kullanmayı düşünebileceğiniz diğer seçenekler

-s, --no-messages         suppress error messages
-D, --devices=ACTION      how to handle devices, FIFOs and sockets;
-Z, --null                print 0 byte after FILE name
-U, --binary              do not strip CR characters at EOL (MSDOS/Windows)


2

Teknik olarak sadece koşmanız gerekiyor ls -lR *.py | md5sum. Birinin dosyaları değiştirip orijinal tarihlerine geri dokunması ve dosyaların boyutlarını asla değiştirmemesi konusunda endişelenmediğiniz sürece, dosyadan alınan çıktı lsdosyanın değişip değişmediğini size söylemelidir. Unix-foo'm zayıf, bu nedenle yazdırmak için oluşturma zamanı ve değiştirme zamanını elde etmek için daha fazla komut satırı parametresine ihtiyacınız olabilir. lsayrıca dosyalar üzerindeki izinlerin değişip değişmediğini de söyleyecektir (ve umursamıyorsanız bunu kapatmak için anahtarlar olduğundan eminim).


3
Bu, bazı kullanım durumlarına uyabilir, ancak genellikle sağlama toplamının tarihleri ​​değil, yalnızca içeriği yansıtmasını istersiniz. Örneğin, eğer ben touchbir dosya onun tarih (ancak değiştirmek için değil içindekileri) o zaman sağlama değişmeden olması beklenebilir.
Todd Owen


1

Aynı problemi yaşadım, bu yüzden dizindeki dosyaların sadece md5sum'larını listeleyen bu komut dosyasını buldum ve eğer bir alt dizin bulursa oradan tekrar çalışır, bunun gerçekleşmesi için komut dosyası mevcut dizinden veya bir alt dizinden, söz konusu bağımsız değişken $ 1'e aktarılırsa

#!/bin/bash

if [ -z "$1" ] ; then

# loop in current dir
ls | while read line; do
  ecriv=`pwd`"/"$line
if [ -f $ecriv ] ; then
    md5sum "$ecriv"
elif [ -d $ecriv ] ; then
    sh myScript "$line" # call this script again
fi

done


else # if a directory is specified in argument $1

ls "$1" | while read line; do
  ecriv=`pwd`"/$1/"$line

if [ -f $ecriv ] ; then
    md5sum "$ecriv"

elif [ -d $ecriv ] ; then
    sh myScript "$line"
fi

done


fi

Dosya adları boşluklar veya tırnak işaretleri içeriyorsa bu komut dosyasının başarısız olacağından oldukça eminim. Bunu bash komut dosyasıyla can sıkıcı buluyorum, ancak yaptığım şey IFS'yi değiştirmek.
localhost

1

Dosya sistemi özniteliklerinden ve bazı tar sürümlerinin bit düzeyi farklılıklarından gerçekten bağımsız olmak istiyorsanız, cpio'yu kullanabilirsiniz:

cpio -i -e theDirname | md5sum

0

İki çözüm daha var:

Oluşturmak:

du -csxb /path | md5sum > file

ls -alR -I dev -I run -I sys -I tmp -I proc /path | md5sum > /tmp/file

Kontrol:

du -csxb /path | md5sum -c file

ls -alR -I dev -I run -I sys -I tmp -I proc /path | md5sum -c /tmp/file

0

md5sumbenim için iyi çalıştı, ancak sortdosya adlarıyla ve dosya adlarını sıralarken sorunlar yaşadım . Bunun yerine md5sumsonuca göre sıraladım . Karşılaştırılabilir sonuçlar oluşturmak için bazı dosyaları da dışlamam gerekiyordu.

find . -type f -print0 \ | xargs -r0 md5sum \ | grep -v ".env" \ | grep -v "vendor/autoload.php" \ | grep -v "vendor/composer/" \ | sort -d \ | md5sum

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.