2016-06-07 13 views
5

कभी-कभी मैं grep-हजारों फ़ाइलों को आउटपुट कैसे कर सकता हूं और किसी प्रकार की प्रगति (बार या स्थिति) देखना अच्छा लगेगा।grep - प्रगति पट्टी या स्थिति

मुझे पता है क्योंकि grepSTDOUT के लिए खोज परिणामों आउटपुट और मेरा डिफ़ॉल्ट कार्यप्रवाह है कि मैं उत्पादन एक फाइल करने के लिए परिणाम होता है और प्रगति बार/स्थिति के उत्पादन होना चाहते हैं यह तुच्छ नहीं है STDOUT या एसटीडीईआरआर

क्या grep के स्रोत कोड को संशोधित करने की आवश्यकता होगी?

आदर्श आदेश है:

grep -e "STRING" --results="FILE.txt"

और प्रगति:

[curr file being searched], number x/total number of files 

लिखा को STDOUT या STDERR

+0

क्या आपने ऐसा करने के लिए एक स्क्रिप्ट का उपयोग करने पर विचार किया है? Grep स्रोत कोड –

उत्तर

7

यह आवश्यक रूप से, grep को संशोधित करने की आवश्यकता नहीं होगी, हालांकि आप शायद इस तरह के एक संशोधन के साथ एक और अधिक सटीक प्रगति बार मिल सकता है।

यदि आप grep के एक ही आमंत्रण के साथ "हजारों फाइलें" grepping कर रहे हैं, तो संभवतः आप -r विकल्प का उपयोग निर्देशिका संरचना के लिए कर रहे हैं।उस स्थिति में, यह भी स्पष्ट नहीं है कि grep जानता है कि यह कितनी फाइलों की जांच करेगा, क्योंकि मेरा मानना ​​है कि यह पूरी निर्देशिका संरचना की खोज करने से पहले फाइलों की जांच शुरू कर देता है। निर्देशिका संरचना का अन्वेषण करने से पहले कुल स्कैन समय में वृद्धि होगी (और, वास्तव में, प्रगति रिपोर्ट बनाने के लिए हमेशा लागत होती है, यही कारण है कि कुछ पारंपरिक यूनिक्स उपयोगिताएं ऐसा करती हैं।)

किसी भी मामले में, एक साधारण लेकिन थोड़ा गलत प्रगति बार बैच का कुल आकार के आधार पर फ़ाइलों को स्कैन करने की की पूरी सूची का निर्माण और फिर कुछ आकार के बैच में grep करने के लिए उन्हें खिलाने, शायद 100 से प्राप्त किया जा सकता है, या हो सकता है। छोटे बैच अधिक सटीक प्रगति रिपोर्ट की अनुमति देंगे लेकिन वे ओवरहेड भी बढ़ाएंगे क्योंकि उन्हें अतिरिक्त जीईपी प्रक्रिया स्टार्ट-अप की आवश्यकता होगी, और प्रक्रिया स्टार्ट-अप समय एक छोटी फ़ाइल को grepping से अधिक हो सकता है। प्रगति रिपोर्ट फाइलों के प्रत्येक बैच के लिए अपडेट की जाएगी, इसलिए आप एक बैच आकार चुनना चाहते हैं जिसने आपको ओवरहेड को बढ़ाने के बिना नियमित अपडेट दिए हैं। फाइलों के कुल आकार पर बैच आकार को बेस करना (उदाहरण के लिए, stat फाइलसाइज प्राप्त करने के लिए) प्रगति रिपोर्ट को और सटीक बना देगा लेकिन स्टार्टअप को संसाधित करने के लिए अतिरिक्त लागत जोड़ें। इस रणनीति का

एक लाभ यह है कि आप भी समानांतर में दो या अधिक greps चला सकते हैं, एक सा प्रक्रिया में तेजी लाने हो सकता है है।


व्यापक संदर्भ में, एक सरल स्क्रिप्ट (जो सिर्फ गिनती करके फ़ाइलें बिताते हैं, आकार से नहीं है, और जो parallelize करने का प्रयास नहीं करता है)।

# Requires bash 4 and Gnu grep 
shopt -s globstar 
files=(**) 
total=${#files[@]} 
for ((i=0; i<total; i+=100)); do 
    echo $i/$total >>/dev/stderr 
    grep -d skip -e "$pattern" "${files[@]:i:100}" >>results.txt 
done 

सादगी के लिए, मैं एक globstar (**) का उपयोग सुरक्षित रूप से एक सरणी में सभी फ़ाइलों डाल करने के लिए। यदि आपके बैश का संस्करण बहुत पुराना है, तो आप इसे find के आउटपुट पर लूप करके कर सकते हैं, लेकिन यदि आपके पास बहुत सारी फ़ाइलें हैं तो यह बहुत प्रभावी नहीं है। दुर्भाग्यवश, मुझे कोई ग्लोबस्टार अभिव्यक्ति लिखने का कोई तरीका नहीं है जो केवल फाइलों से मेल खाता है। (**/ केवल निर्देशिका से मेल खाता है।) सौभाग्य से, GNU grep -d skip विकल्प प्रदान करता है जो चुपचाप निर्देशिकाओं को छोड़ देता है। इसका मतलब है कि फ़ाइल गिनती थोड़ी गलत होगी, क्योंकि निर्देशिकाओं की गणना की जाएगी, लेकिन शायद यह बहुत अंतर नहीं करता है।

आप शायद कुछ सांत्वना कोड का उपयोग करके प्रगति रिपोर्ट क्लीनर बनाने के लिए चाहते हैं। उपर्युक्त बस आपको शुरू करने के लिए है।

विभाजित करने के लिए है कि विभिन्न प्रक्रियाओं में सिर्फ एक्स भिन्न खंडों में सूची विभाजित और छोरों के लिए X अलग, एक अलग प्रारंभिक बिंदु के साथ प्रत्येक को चलाने के लिए किया जाएगा सबसे आसान तरीका है। हालांकि, वे शायद एक ही समय में खत्म नहीं होंगे ताकि उप-इष्टतम हो। बेहतर समाधान जीएनयू समानांतर है। आप कुछ इस तरह कर सकते हैं:

find . -type f -print0 | 
parallel --progress -L 100 -m -j 4 grep -e "$pattern" > results.txt 

(यहाँ -L 100 निर्दिष्ट करता है कि अप करने के लिए 100 फ़ाइलें प्रत्येक ग्रेप उदाहरण को दी जानी चाहिए, और -j 4 चार समानांतर प्रक्रियाओं को निर्दिष्ट करता है मैं सिर्फ उन संख्याओं को हवा से बाहर खींच लिया, तुम '। शायद उन्हें समायोजित करना चाहेंगे।)

+0

बहुत अच्छा और लगभग पूरा जवाब। कृपया कार्य को पूरा करने के लिए 'ढूंढें, समांतर, grep' आदेशों का उपयोग करने के तरीके पर एक उदाहरण पोस्ट करें और मैं इसे स्वीकार किए जाने के रूप में चिह्नित करूंगा। – Adrian

+0

@adrian: यह जानने में मदद करेगा कि आप वर्तमान में grep का आविष्कार कैसे कर रहे हैं: '-r' चीज़ सिर्फ एक अनुमान था। – rici

+0

मेरा सामान्य grep कमांड 'grep -e "STRING" * -r' है। * एक समय में एक्स फाइलों का बैच करना एक आदर्श विचार है। – Adrian

0

मैं बहुत यकीन है कि आप की आवश्यकता होगी कर रहा हूँ grep स्रोत कोड को बदलें। और वे परिवर्तन बहुत बड़े होंगे।

वर्तमान में grep यह नहीं जानता कि फ़ाइल कितनी लाइनें पूरी फ़ाइल को पार करने तक समाप्त होती है। आपकी आवश्यकता के लिए इसे फ़ाइल को 2 बार पार्स करना होगा या कम से कम पूर्ण लाइन गिनती को किसी अन्य तरीके से निर्धारित करना होगा।

पहली बार यह प्रगति पट्टी के लिए रेखा गणना निर्धारित करेगा। दूसरी बार यह वास्तव में काम को आपके पैटर्न की खोज करेगा।

यह न केवल रनटाइम को बढ़ाएगा बल्कि मुख्य यूनिक्स दर्शनों में से एक का उल्लंघन करेगा।

  1. प्रत्येक प्रोग्राम को एक चीज़ अच्छी तरह से करें। नई नौकरी करने के लिए, नए "फीचर्स" जोड़कर पुराने कार्यक्रमों को जटिल बनाने के बजाय नए बनाएं। (source)

वहाँ अन्य उपकरण अपनी जरूरत के लिए वहाँ बाहर हो सकता है, लेकिन ग्रेप afaik यहां फिट नहीं होगा।

grep | tee "FILE.txt" | cat -n | sed 's/^/match: /;s/$/  /' | tr '\n' '\r' 1>&2 

यह सही नहीं है, क्योंकि यह केवल मिलान प्रदर्शित करता है अगर वे लंबे समय तक के लिए, और या लंबाई में बहुत अलग त्रुटियां होने, लेकिन यह प्रदान करना चाहिए:

+1

संपादित करने से यह आसान है ओपी लाइन गणनाओं के बारे में कुछ भी नहीं कहता है, केवल फाइलें।और यह भी स्पष्ट नहीं है कि रेखा गणना उपयोगी होगी; इकट्ठा करने के लिए एक सरल आंकड़ा कुल बाइट्स (जिसे आप कॉल से स्टेट तक प्राप्त कर सकते हैं) होगा, और यह एक और सटीक आंकड़ा भी होगा, क्योंकि grep वास्तव में ब्लॉक में पढ़ता है, लाइनों पर नहीं। हालांकि, मैं आपके उत्तर के मूल दर्शन से सहमत हूं। – rici

+0

क्षमा करें, मैंने आउटपुट 'संख्या x' को गलत समझा, जिसका अर्थ है कि वह फ़ाइल वाई में लाइन x का मतलब है। – cb0

1

मैं normaly कुछ इस तरह का उपयोग करें आप सामान्य विचार के साथ।

या एक सरल डॉट्स:

grep | tee "FILE.txt" | sed 's/.*//' | tr '\n' '.' 1>&2 
+1

यह स्थिति कैसे इंगित करता है? – Adrian

+0

'grep -e" STRING "| टीई "FILE.txt" 'उम्मीद है कि आपके 'grep -e" STRING "--results =" FILE.txt "का उत्तर है, लेकिन यह' x/फाइलों की कुल संख्या 'जैसी पूर्ण स्थिति नहीं है। । यह सिर्फ पहले से संसाधित मैचों की संख्या दिखाता है। –

1

समानांतर कार्यक्रम

find * -name \*.[ch] | parallel -j5 --bar '(grep grep-string {})' > output-file 

प्रयास करें हालांकि मैंने पाया यह एक सरल

की तुलना में धीमी होने के लिए
find * -name \*.[ch] | xargs grep grep-string > output-file 
संबंधित मुद्दे