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 ।