यह आवश्यक रूप से, 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
चार समानांतर प्रक्रियाओं को निर्दिष्ट करता है मैं सिर्फ उन संख्याओं को हवा से बाहर खींच लिया, तुम '। शायद उन्हें समायोजित करना चाहेंगे।)
क्या आपने ऐसा करने के लिए एक स्क्रिप्ट का उपयोग करने पर विचार किया है? Grep स्रोत कोड –