मैं एक निर्देशिका के md5 चेकसम की गणना कैसे कर सकता हूं?


133

मुझे *.pyएक निर्देशिका और सभी उप-निर्देशिकाओं के तहत रखी गई एक विशेष प्रकार ( उदाहरण के लिए) की सभी फाइलों के लिए एक सारांश md5 चेकसम की गणना करने की आवश्यकता है ।

उसे करने का सबसे अच्छा तरीका कौन सा है?

संपादित करें: प्रस्तावित समाधान बहुत अच्छे हैं, लेकिन यह वही नहीं है जो मुझे चाहिए। मैं एक एकल सारांश चेकसम प्राप्त करने के लिए एक समाधान की तलाश कर रहा हूं जो कि पूरी तरह से निर्देशिका की पहचान करेगा - जिसमें इसके सभी उप-निर्देशिकाओं की सामग्री भी शामिल है।


पर एक नजर डालें इस और इस एक अधिक विस्तृत विवरण के लिए।
लूविएरे

3
मेरे लिए एक सुपरयूजर प्रश्न की तरह लगता है।
नोल्डोरिन

8
ध्यान दें कि चेकसम विशिष्ट रूप से किसी भी चीज़ की पहचान नहीं करता है।
होसाम ऐली

1
आपके पास दो निर्देशिका पेड़ क्यों होंगे जो "समान" हो सकते हैं या नहीं जो आप विशिष्ट रूप से पहचान करना चाहते हैं? क्या फ़ाइल बनाने / संशोधित करने / एक्सेस टाइम की बात करता है? क्या संस्करण नियंत्रण आपके लिए वास्तव में आवश्यक है?
jmucchiello

मेरे मामले में वास्तव में जो बात है वह पूरी निर्देशिका वृक्ष सामग्री की समानता है जिसका अर्थ है AFAIK निम्नलिखित: 1) निर्देशिका पेड़ के नीचे किसी भी फाइल की सामग्री को 2 नहीं बदला गया है) कोई नया फ़ाइल निर्देशिका ट्री 3 में जोड़ा गया था) कोई फ़ाइल नहीं को हटा दिया गया था
विजोरेज़

जवाबों:


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

खोज आदेश उन सभी फ़ाइलों को सूचीबद्ध करता है जो .py में समाप्त होती हैं। Md5sum की गणना प्रत्येक .py फ़ाइल के लिए की जाती है। awk का उपयोग md5sums को निकालने के लिए किया जाता है (फाइलन की अनदेखी, जो अद्वितीय नहीं हो सकता है)। Md5sums क्रमबद्ध हैं। इस क्रमबद्ध सूची के md5sum को फिर लौटा दिया जाता है।

मैंने परीक्षण निर्देशिका की प्रतिलिपि बनाकर यह परीक्षण किया है:

rsync -a ~/pybin/ ~/pybin2/

मैंने कुछ फ़ाइलों का नाम बदलकर ~ / pybin2 कर दिया है।

find...md5sumआदेश दोनों निर्देशिकाओं के लिए एक ही आउटपुट देता है।

2bcf49a4d19ef9abd284311108d626f1  -

24
ध्यान दें कि यदि फ़ाइल का नाम बदला जाता है तो वही चेकसम उत्पन्न किया जाएगा। यदि आप हस्ताक्षर के फ़ाइल लेआउट भाग पर विचार करते हैं, तो यह वास्तव में "चेकसम" के रूप में पूरी तरह से निर्देशिका की पहचान नहीं करता है जो फिट बैठता है।
वैलेंटाइन मिला

1
आप फ़ाइल के नाम के साथ प्रत्येक फ़ाइल चेकसम को उपसर्ग करने के लिए कमांड-लाइन को थोड़ा बदल सकते हैं (या इससे भी बेहतर, फ़ाइल के सापेक्ष पथ / पथ / से / dir /) ताकि इसे अंतिम चेकसम में ध्यान में रखा जाए।
माइकल ज़िल्बरमैन

4
@ zim2001: हां, इसमें बदलाव किया जा सकता है, लेकिन जैसा कि मैंने समस्या को समझा (विशेषकर ओपी की टिप्पणी के तहत सवाल के कारण), ओपी चाहता था कि किसी भी दो निर्देशिकाओं को समान माना जाए, यदि फ़ाइलों की सामग्री फ़ाइल नाम की परवाह किए बिना समान थी। यहां तक ​​कि रिश्तेदार पथ।
unutbu

@unutbu: मुझे पता है; मैं वैलेंटाइन मिलिया से पिछले नोट पर प्रतिक्रिया दे रहा था।
माइकल ज़िल्बरमैन

awk ...यदि आप हस्ताक्षर के लेआउट भाग पर विचार करते हैं तो @ValentinMilea भाग को हटा दें ।
segfault

166

मक्खी और पाइप पर एक टार आर्काइव फ़ाइल बनाएँ md5sum:

tar c dir | md5sum

यह एक एकल md5sum पैदा करता है जो आपकी फ़ाइल और उप-निर्देशिका सेटअप के लिए अद्वितीय होना चाहिए। डिस्क पर कोई फ़ाइल नहीं बनाई गई हैं।


25
@ एकल जाँच-राशि के साथ CharlesB आप कभी नहीं जानते कि कौन सी फ़ाइल अलग है। एक निर्देशिका के लिए प्रश्न एकल चेक-योग के बारे में था।
हकेन

17
ls -alR dir | md5sum। यह सिर्फ एक पढ़ने के लिए कोई संपीड़न भी बेहतर है। यह अद्वितीय है क्योंकि सामग्री में फ़ाइल का मॉड समय और आकार शामिल है;)
सिड

14
@ Daps0l - मेरी कमांड में कोई कंपटीशन नहीं है। आपको zgzip के लिए, या jbzip2 के लिए जोड़ना होगा । मैंने न तो किया है।
ire_and_curses

7
ध्यान रखें कि ऐसा करने से फाइलों की टाइमस्टैम्प और चेकसम संगणना में अन्य सामान को एकीकृत किया जाएगा, न केवल फाइलों की सामग्री
माइकल Zilbermann

10
यह प्यारा है, लेकिन यह वास्तव में काम नहीं करता है। इस बात की कोई गारंटी नहीं है कि tarफ़ाइलों के एक ही सेट को दो बार या दो अलग-अलग कंप्यूटरों पर एक ही सटीक परिणाम प्राप्त होगा।
fletom

46

ire_and_curses के उपयोग के सुझाव tar c <dir>में कुछ समस्याएं हैं:

  • टार डायरेक्टरी प्रविष्टियों को उस क्रम में संसाधित करता है जिसे वे फाइलसिस्टम में संग्रहित करते हैं, और इस क्रम को बदलने का कोई तरीका नहीं है। यह प्रभावी रूप से पूरी तरह से अलग परिणाम दे सकता है यदि आपके पास अलग-अलग स्थानों पर "समान" निर्देशिका है, और मुझे पता है कि इसे ठीक करने का कोई तरीका नहीं है (किसी विशेष क्रम में इसकी इनपुट फ़ाइलों को टार नहीं कर सकता है)।
  • मैं आमतौर पर इस बात की परवाह करता हूं कि क्या समूह और मालिक संख्या समान हैं, जरूरी नहीं कि समूह / स्वामी का स्ट्रिंग प्रतिनिधित्व समान हो। यह उदाहरण के लिए क्या rsync -a --deleteकरता है के साथ है: यह वस्तुतः सब कुछ (माइनस xattrs और acls) को सिंक्रनाइज़ करता है, लेकिन यह स्वामी और समूह को उनकी आईडी के आधार पर सिंक करेगा, न कि स्ट्रिंग प्रतिनिधित्व पर। इसलिए यदि आपने एक अलग प्रणाली को सिंक किया है, जिसमें जरूरी नहीं कि समान उपयोगकर्ता / समूह हों, तो आपको --numeric-ownerध्वज को टार में जोड़ना चाहिए
  • टार में उस निर्देशिका का फ़ाइल नाम शामिल होगा जिसे आप स्वयं जाँच रहे हैं, बस कुछ के बारे में पता होना चाहिए।

जब तक पहली समस्या के लिए कोई ठीक नहीं है (या जब तक आप सुनिश्चित नहीं हैं कि यह आपको प्रभावित नहीं करता है), मैं इस दृष्टिकोण का उपयोग नहीं करूंगा।

findऊपर प्रस्तावित आधारित समाधान भी अच्छा नहीं है क्योंकि वे केवल फ़ाइलें, नहीं निर्देशिका है, जो एक मुद्दा अगर आप checksumming मन खाली निर्देशिका में रखना चाहिए हो जाता है शामिल हैं।

अंत में, अधिकांश सुझाए गए समाधान लगातार क्रमबद्ध नहीं होते हैं, क्योंकि कोलाज पूरे सिस्टम में भिन्न हो सकते हैं।

यह वह उपाय है जो मैं लेकर आया हूं:

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

इस समाधान के बारे में नोट्स:

  • LC_ALL=Cसिस्टम में विश्वसनीय छंटाई सुनिश्चित करने के लिए है
  • यह एक निर्देशिका "नामित \ nwithanewline" और दो निर्देशिकाओं "नाम" और "withanewline" के बीच अंतर नहीं करता है, लेकिन इस बात की संभावना बहुत कम लगती है। एक आमतौर पर इसे एक -print0ध्वज के साथ ठीक करता है , findलेकिन चूंकि यहां अन्य सामान चल रहा है, मैं केवल समाधान देख सकता हूं जो कमांड को अधिक जटिल बना देगा फिर यह लायक है।

पुनश्च: मेरे सिस्टम में से एक सीमित व्यस्त बॉक्स का उपयोग करता है findजो -execन तो -print0झंडे का समर्थन करता है , और न ही यह निर्देशिकाओं को निरूपित करने के लिए '/' को जोड़ता है, जबकि ढूंढने में लगता नहीं है, इसलिए इस मशीन के लिए मुझे चलाने की आवश्यकता है:

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

सौभाग्य से, मेरे पास उनके नाम की नई लाइनों के साथ कोई फाइल / निर्देशिका नहीं है, इसलिए यह उस प्रणाली पर कोई समस्या नहीं है।


1
+1: बहुत दिलचस्प! क्या आप कह रहे हैं कि आदेश अलग-अलग फाइल सिस्टम के बीच, या एक ही फाइल सिस्टम के बीच भिन्न हो सकता है?
ire_and_curses

2
दोनों। यह सिर्फ प्रत्येक निर्देशिका के भीतर निर्देशिका प्रविष्टियों के क्रम पर निर्भर करता है। AFAIK निर्देशिका प्रविष्टियाँ (फाइल सिस्टम में) सिर्फ उसी क्रम में बनाई जाती हैं जिसमें आप "डायरेक्टरी में फाइल बनाते हैं"। एक सरल उदाहरण: $ mkdir a; / a-file-1 को स्पर्श करें; / a-file-2 $ mkdir b स्पर्श करें; टच बी / फाइल -2; स्पर्श बी / फ़ाइल-1 $ (सीडी एक; टार -c | md5sum।) fb29e7af140aeea5a2647974f7cdec77 - $ (सीडी ख;। टार -c | md5sum) a3a39358158a87059b9f111ccffa1023 -
Dieter_be

15

यदि आप केवल फाइलों की परवाह करते हैं और खाली निर्देशिकाओं की नहीं, तो यह अच्छी तरह से काम करता है:

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

10

पूर्णता के लिए, वहाँ md5deep (1) है ; * .py फ़िल्टर की आवश्यकता के कारण यह सीधे लागू नहीं होता है, लेकिन इसे खोजने (1) के साथ ठीक करना चाहिए।


अगर मैं केवल निर्देशिका के md5 चेकसम की गणना करना चाहता हूं तो मैं किन मापदंडों का उपयोग करूंगा?
गेब्रियल फेयर

9

एक समाधान जो मेरे लिए सबसे अच्छा काम करता है:

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

कारण यह मेरे लिए सबसे अच्छा काम किया:

  1. रिक्त स्थान वाले फ़ाइल नामों को संभालता है
  2. फाइलसिस्टम मेटा-डेटा को अनदेखा करता है
  3. पता लगाता है कि फ़ाइल का नाम बदला गया है या नहीं

अन्य जवाब के साथ मुद्दे:

फ़ाइल सिस्टम मेटा-डेटा की उपेक्षा नहीं की जाती है:

tar c - "$path" | md5sum

यदि फ़ाइल का नाम बदल दिया गया है, तो न तो रिक्त स्थान को संभालता है और न ही पता लगाता है:

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

4

यदि आप चाहते हैं कि पूरी निर्देशिका में एक md5sum फैले, तो मैं कुछ ऐसा करूंगा

cat *.py | md5sum 

1
उपप्राणियों के लिए कुछ का उपयोग करें cat **.py| md5sum
रेमन

3

सामग्री और उनके फ़ाइल नाम दोनों सहित सभी फ़ाइलों की जाँच करें

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

ऊपर के रूप में ही, लेकिन * .py फ़ाइलों सहित

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

आप चाहें तो सिमिलिंक का पालन भी कर सकते हैं

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

अन्य विकल्प जिन्हें आप grep के साथ उपयोग करने पर विचार कर सकते हैं

-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

तकनीकी रूप से आपको केवल चलाने की आवश्यकता है ls -lR *.py | md5sum। जब तक आप किसी को फ़ाइलों को संशोधित करने और उन्हें उनकी मूल तिथियों में वापस छूने और फ़ाइलों के आकार को कभी नहीं बदलने के बारे में चिंतित हैं, तो आउटपुट से आपको lsयह बताना चाहिए कि क्या फ़ाइल बदल गई है। मेरा यूनिक्स-फू कमजोर है, इसलिए आपको प्रिंट बनाने के लिए समय और संशोधन समय प्राप्त करने के लिए कुछ और कमांड लाइन मापदंडों की आवश्यकता हो सकती है। lsआपको यह भी बताएगा कि क्या फाइलों पर अनुमति बदल गई है (और मुझे यकीन है कि स्विच बंद हैं यदि आप उस बारे में परवाह नहीं करते हैं)।


3
यह कुछ उपयोग मामलों में फिट हो सकता है, लेकिन आम तौर पर आप चाहते हैं कि चेकसम केवल सामग्री को प्रतिबिंबित करे और तारीखों को बिल्कुल भी न दिखाए। उदाहरण के लिए, यदि मैं touchइसकी तारीख (लेकिन इसकी सामग्री नहीं ) को बदलने के लिए एक फ़ाइल करता हूं तो मुझे उम्मीद है कि चेकसम अपरिवर्तित होगा।
टोड ओवेन


1

मुझे भी यही समस्या थी इसलिए मैं इस स्क्रिप्ट के साथ आया था कि बस निर्देशिका में फ़ाइलों के md5sums को सूचीबद्ध करता है और अगर यह एक उपनिर्देशिका पाता है तो यह फिर से वहां से चलता है, इसके लिए स्क्रिप्ट को वर्तमान के माध्यम से चलाने में सक्षम होना चाहिए निर्देशिका या एक उपनिर्देशिका से अगर तर्क $ 1 में पारित किया गया है

#!/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

मुझे पूरा यकीन है कि अगर फ़ाइलनाम में स्थान या उद्धरण हैं तो यह स्क्रिप्ट विफल हो जाएगी। मुझे यह बैश स्क्रिप्टिंग से परेशान लगता है, लेकिन मैं जो करता हूं वह IFS को बदल देता है।
लोकलहोस्टेन

1

यदि आप फ़ाइल सिस्टम विशेषताओं और कुछ टार संस्करणों के बिट-लेवल अंतर से वास्तव में स्वतंत्र चाहते हैं, तो आप cpio का उपयोग कर सकते हैं:

cpio -i -e theDirname | md5sum

0

दो और उपाय हैं:

सृजन करना:

du -csxb /path | md5sum > file

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

जाँच:

du -csxb /path | md5sum -c file

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

0

md5sumमेरे लिए ठीक काम किया, लेकिन मेरे पास sortफ़ाइल नामों के साथ समस्याएँ थीं । इसलिए इसके बजाय मैंने md5sumपरिणाम के अनुसार हल किया । तुलनीय परिणाम बनाने के लिए मुझे कुछ फ़ाइलों को बाहर करने की भी आवश्यकता थी।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.