2012-01-24 14 views
6

मैंने साइगविन पर एक बैश स्क्रिप्ट लिखी है जो rsync की तरह है, हालांकि मुझे लगता है कि मैं वास्तव में rsync का उपयोग करने के लिए वास्तव में उपयोग नहीं कर सकता हूं। यह संबंधित निर्देशिकाओं में फ़ाइलों के बारे में एक हजार जोड़े से अधिक है, उन्हें cmp के साथ तुलना करता है।सिगविन पर फ़ाइल तुलना (`cmp` के साथ) को तेज करना?

दुर्भाग्यवश, यह लगभग धीरे-धीरे चल रहा है - लगभग दस (संपादित करें: वास्तव में 25!) बार जब तक यह एक पायथन प्रोग्राम का उपयोग कर फ़ाइलों के सेटों में से एक उत्पन्न करने के लिए लेता है।

क्या मैं सोच रहा हूं कि यह आश्चर्यजनक रूप से धीमा है? क्या कोई आसान विकल्प है जो तेजी से बढ़ेगा?

(मेरी यूज-केस पर थोड़ा विस्तार से बता दें: मैं एक अस्थायी निर्देशिका में .c फाइलों का एक समूह autogenerating रहा हूँ, और उन्हें जब मैं दोबारा बनाने, मैं केवल लोगों को बदल दिया है कि कॉपी करना चाहते हैं वास्तविक स्रोत निर्देशिका में, अपरिवर्तित लोगों को बिना छेड़छाड़ किए गए (उनके पुराने निर्माण समय के साथ) छोड़कर make पता चलेगा कि उन्हें पुन: संकलित करने की आवश्यकता नहीं है। सभी जेनरेट की गई फ़ाइलें .c फ़ाइलें नहीं हैं, हालांकि, मुझे बाइनरी करने की आवश्यकता है पाठ तुलना की तुलना में तुलना।)

+0

इसके लायक होने के लिए, मैंने पुष्टि की है कि 'rsync' जो मैं चाहता हूं वह नहीं करता है; यह हमेशा अपरिवर्तित फ़ाइलों पर संशोधित समय को रीसेट करता है, या तो मूल पर टाइमस्टैंप (यदि '-t' के साथ कहा जाता है) या स्थानांतरण के समय तक। –

+0

दिलचस्प समस्या..मुझे लगता है कि यह फ़ाइल के टाइमस्टैम्प को अपडेट करने से सिंक को रोकने के तरीके के बारे में भी पूछना उचित है, यह –

+0

@MiserableVariable स्थानांतरित नहीं किया गया है: अच्छा विचार - अब यह है http://unix.stackexchange.com/questions/29845/ कैसे-कर सकते हैं-मैं करते हैं-एक कॉपी-अगर-बदल आपरेशन। (मुझे नहीं लगता कि यह एक डुप्लिकेट है; यह है "मैं इस कार्यक्रम को बेहतर कैसे लिखूं", जबकि यह है "क्या मैं इसे पूरी तरह से टाल सकता हूं?"। –

उत्तर

3

शायद आपको कुछ काम करने के लिए पाइथन का उपयोग करना चाहिए - या यहां तक ​​कि सभी तुलनात्मक काम भी?

एक सुधार केवल cmp चलाने के लिए परेशान होगा यदि फ़ाइल आकार समान हैं; अगर वे अलग हैं, तो स्पष्ट रूप से फ़ाइल बदल गई है। cmp चलाने के बजाय, आप MD5 या SHA1 या SHA-256 का उपयोग करके प्रत्येक फ़ाइल के लिए हैश उत्पन्न करने के बारे में सोच सकते हैं या जो कुछ भी आपकी कल्पना लेता है (पाइथन मॉड्यूल या एक्सटेंशन का उपयोग करके, यदि यह सही शब्द है)। यदि आपको नहीं लगता कि आप दुर्भावनापूर्ण इरादे से निपटेंगे, तो एमडी 5 अंतर की पहचान करने के लिए शायद पर्याप्त है।

यहां तक ​​कि एक शेल स्क्रिप्ट में, आप बाहरी हैशिंग कमांड चला सकते हैं, और इसे एक निर्देशिका में सभी फ़ाइलों का नाम दे सकते हैं, फिर उसे अन्य निर्देशिका में सभी फ़ाइलों का नाम दें। फिर आप हैश मानों के साथ-साथ फ़ाइल नामों के दो सेट पढ़ सकते हैं और तय कर सकते हैं कि कौन सा बदल गया है।

हां, ऐसा लगता है जैसे यह बहुत लंबा समय ले रहा है। लेकिन इस समस्या में cmp की 1000 प्रतियां, साथ ही अन्य प्रसंस्करण को लॉन्च करना शामिल है। उपरोक्त पायथन और शैल स्क्रिप्ट सुझावों में दोनों समान हैं कि वे 1000 बार प्रोग्राम चलाने से बचते हैं; वे निष्पादित कार्यक्रमों की संख्या को कम करने की कोशिश करते हैं। निष्पादित प्रक्रियाओं की संख्या में यह कमी आपको मेरे लिए एक बहुत बड़ी धमाके देगी, मुझे उम्मीद है।


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

एक अन्य संभावना: क्या आप इन फ़ाइलों को उत्पन्न करने के लिए उपयोग किए जाने वाले डेटा में परिवर्तनों को ट्रैक कर सकते हैं और यह बताने के लिए उपयोग कर सकते हैं कि कौन सी फाइलें बदली होंगी (या, कम से कम, फ़ाइलों के सेट को सीमित कर सकते हैं जो कि हो सकते हैं और इसलिए इसकी तुलना करने की आवश्यकता है, क्योंकि आपकी टिप्पणियां इंगित करती हैं कि अधिकांश फाइलें हर बार समान होती हैं)।

+2

एमडी 5 और अन्य हैश संस्करण का लाभ यह है कि आप बाइट-बाय-बाइट तुलना करने के बजाए हैश स्टोर कर सकते हैं _next_ पुनरावृत्ति पर। यदि आप पुरानी फाइलों और नई फाइलों के लिए प्रत्येक बार एमडी 5 की फिर से गणना करते हैं, तो यह बहुत अलग नहीं है। – sarnold

+0

सहमत हैं, यह स्पष्ट रूप से समस्या है। निर्देशिकाओं में से किसी एक में फ़ाइलों पर 'md5sum *' चलाना बहुत तेज़ है, और (जैसा कि @ कर्नाल्ड का तात्पर्य है) केवल "असली" लाभ है कि यह केवल एक प्रोग्राम शुरू कर रहा है; यह वही डेटा लोड कर रहा है। अब यह पता लगाने के लिए कि क्या मुझे वहां से प्राप्त करने के लिए एक आसान तरीका है .... –

+0

@ कर्नाल्ड: राइट - पायथन संस्करण में, अगर उन्हें संग्रहीत नहीं किया जा रहा है तो MD5 हैश की गणना करने में कोई बात नहीं है। –

1

यदि आप हजारों अतिरिक्त कार्यक्रमों को बढ़ाने और निष्पादित करने के बजाय एक प्रक्रिया के भीतर एक हजार अजीब फ़ाइलों की तुलना कर सकते हैं, तो यह संभवतः आदर्श होगा।

संक्षिप्त उत्तर: --silent अपने cmp कॉल में शामिल करें, अगर यह वहाँ नहीं पहले से ही है।

आप डेटा की जांच करने से पहले कुछ फ़ाइल आकार जांच करके पाइथन संस्करण को तेज़ करने में सक्षम हो सकते हैं।

सबसे पहले, एक त्वरित और hacky bash(1) तकनीक है कि काफी आसान है, तो आप एक ही build निर्देशिका को बदल सकते हैं हो सकता है: bash-N परीक्षण का उपयोग करें:,

$ echo foo > file 
$ if [ -N file ] ; then echo newer than last read ; else echo older than last read ; fi 
newer than last read 
$ cat file 
foo 
$ if [ -N file ] ; then echo newer than last read ; else echo older than last read ; fi 
older than last read 
$ echo blort > file # regenerate the file here 
$ if [ -N file ] ; then echo newer than last read ; else echo older than last read ; fi 
newer than last read 
$ 
बेशक

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

अपने अजगर कार्यक्रम के भीतर, आप भी फ़ाइल आकार निर्धारित करने के लिए किया जाए या नहीं आप अपने तुलना दिनचर्या बुलाना चाहिए os.stat() का उपयोग कर जांच कर सकता है; अगर फाइलें अलग-अलग आकार हैं, तो आप वास्तव में परवाह नहीं करते कि कौन से बाइट बदल गए हैं, ताकि आप दोनों फाइलें पढ़ सकें। (यह bash(1) में करने के लिए मुश्किल होगा - मैं एक कार्यक्रम है, जो इस चेक के पूरे मुद्दे धरा को क्रियान्वित करने के बिना bash(1) में फ़ाइल आकार पाने के लिए कोई तंत्र के बारे में पता।)

cmp कार्यक्रम आकार तुलना करना होगा आंतरिक रूप से IFF आप --silent ध्वज और दोनों फ़ाइलों का उपयोग कर रहे हैं नियमित फ़ाइलें और दोनों फाइलें एक ही स्थान पर स्थित हैं। (यह --ignore-initial ध्वज के माध्यम से सेट किया गया है।) यदि आप --silent का उपयोग नहीं कर रहे हैं, तो इसे जोड़ें और देखें कि अंतर क्या है।

+1

इसके लायक होने के लिए, मैं '--silent' का उपयोग कर रहा हूं।साथ ही, मुझे ध्यान रखना चाहिए कि इसे "लगभग सभी फाइल मिलान" मामले के लिए अनुकूलित करने की आवश्यकता है - अधिकांश समय जब मैं इसे कॉल करता हूं, तो मैंने वास्तव में जेनरेट की गई फ़ाइलों में से कुछ को बदल दिया है। फिर भी, उपयोगी सलाह। –

संबंधित मुद्दे