1।
पहले वाला:
for f in *; do
echo "$f"
done
फाइल के लिए विफल रहता है -n, -eऔर -neneकुछ बैश तैनाती के साथ और वैरिएंट के साथ, बैकलेश युक्त फ़ाइल नाम के साथ।
दूसरा:
find * -prune | while read f; do
echo "$f"
done
और भी अधिक मामलों के लिए विफल रहता है (फ़ाइलों कहा जाता है !, -H, -name, (, फ़ाइल नाम है कि शुरू करने या रिक्त स्थान के साथ अंत या नई पंक्ति वर्ण हो ...)
यह वह खोल है जो फैलता है *, findकुछ भी नहीं करता है लेकिन इसे प्राप्त फाइलों को तर्क के रूप में प्रिंट करता है। आप के रूप में अच्छी तरह से इस्तेमाल किया जा सकता है printf '%s\n'जो के रूप printfमें बनाया गया है भी कई संभावित संभावित त्रुटि से बचना होगा ।
2।
के विस्तार *को क्रमबद्ध किया गया है, यदि आप छंटाई की आवश्यकता नहीं है, तो आप इसे थोड़ा तेज़ कर सकते हैं। इन zsh:
for f (*(oN)) printf '%s\n' $f
या केवल:
printf '%s\n' *(oN)
bashजहाँ तक मैं बता सकता हूँ, उसके बराबर नहीं है, इसलिए आपको इसका सहारा लेना होगा find।
3।
find . ! -name . -prune ! -name '.*' -print0 |
while IFS= read -rd '' f; do
printf '%s\n' "$f"
done
(एक GNU / BSD -print0गैर-मानक विस्तार का उपयोग करके ऊपर )।
इसमें अभी भी एक खोज कमांड को शामिल करना और एक धीमी while readलूप का उपयोग करना शामिल है , इसलिए यह संभवतः forलूप का उपयोग करने की तुलना में धीमा होगा जब तक कि फ़ाइलों की सूची विशाल न हो।
4।
इसके अलावा, शेल वाइल्डकार्ड के विस्तार के विपरीत, प्रत्येक फ़ाइल पर findएक lstatसिस्टम कॉल करेगा, इसलिए यह संभव नहीं है कि गैर-छंटाई उस के लिए क्षतिपूर्ति करेगी।
GNU / BSD के साथ find, उनके -maxdepthविस्तार का उपयोग करके इससे बचा जा सकता है जो एक अनुकूलन बचत को ट्रिगर करेगा lstat:
find . -maxdepth 1 ! -name '.*' -print0 |
while IFS= read -rd '' f; do
printf '%s\n' "$f"
done
क्योंकि findजैसे ही उन्हें (stdio आउटपुट बफ़रिंग को छोड़कर) यह फ़ाइल नामों को आउटपुट करना शुरू कर देता है, जहाँ यह तेज़ हो सकता है यदि आप लूप में जो कर रहे हैं वह समय लेने वाला है और फ़ाइल नामों की सूची एक stdio बफर से अधिक है (4) / 8 केबी)। उस स्थिति में, लूप के भीतर प्रसंस्करण शुरू हो जाएगा इससे पहले findकि सभी फाइलों को ढूंढना समाप्त हो जाए। जीएनयू और फ्रीबीएसडी सिस्टम पर, आप इसका उपयोग stdbufजल्द से जल्द (स्टीडियो बफरिंग को अक्षम करने) करने के लिए कर सकते हैं ।
5।
POSIX / मानक / पोर्टेबल तरीका के साथ प्रत्येक फ़ाइल के लिए कमांड चलाने के लिए विधेय findका उपयोग करना -execहै:
find . ! -name . -prune ! -name '.*' -exec some-cmd {} ';'
echoहालांकि, इस मामले में शेल में लूपिंग करने की तुलना में कम कुशल है क्योंकि शेल का एक अंतर्निहित संस्करण होगा , echoजबकि findएक नई प्रक्रिया को स्पॉन करने और /bin/echoप्रत्येक फ़ाइल के लिए इसे निष्पादित करने की आवश्यकता होगी ।
यदि आपको कई कमांड चलाने की आवश्यकता है, तो आप कर सकते हैं:
find . ! -name . -prune ! -name '.*' -exec cmd1 {} ';' -exec cmd2 {} ';'
लेकिन सावधान रहें जो सफल होने पर cmd2ही निष्पादित होता cmd1है।
6।
प्रत्येक फ़ाइल के लिए जटिल कमांड चलाने के लिए एक कैनोनिकल तरीका है -exec ... {} +:
find . ! -name . -prune ! -name '.*' -exec sh -c '
for f do
cmd1 "$f"
cmd2 "$f"
done' sh {} +
उस समय के बाद से, हम कुशल होने के साथ वापस आ गए हैं echoक्योंकि हम shबिल्टइन का उपयोग कर रहे हैं और -exec +संस्करण shजितना संभव हो उतना कम हो।
7।
में 200.000 फाइलों के साथ एक निर्देशिका पर मेरी परीक्षण ext4 पर कम नामों के साथ, zshएक (अनुच्छेद 2.), अब तक सबसे तेजी से कर रहा है पहले सरल के बाद for i in *पाश (हालांकि हमेशा की तरह, bashएक बहुत कि के लिए अन्य गोले की तुलना में धीमी है)।
findयह पाया फ़ाइलों को नहीं खोलता है। बड़ी संख्या में फ़ाइलों के संबंध में केवल एक चीज जिसे मैं आपको काटता हुआ देख सकता हूं वह है ARG_MAX ।