संक्षिप्त जवाब:
\ls -afq | wc -l
(इसमें शामिल है .
और ..
इसलिए, घटाना 2.)
जब आप फ़ाइलों को किसी निर्देशिका में सूचीबद्ध करते हैं, तो तीन सामान्य चीजें हो सकती हैं:
- निर्देशिका में फ़ाइल नामों की गणना। यह अपरिहार्य है: फ़ाइलों को किसी निर्देशिका में गणना किए बिना उन्हें गिनने का कोई तरीका नहीं है।
- फ़ाइल नामों को छाँटना। शैल वाइल्डकार्ड और
ls
कमांड ऐसा करते हैं।
stat
प्रत्येक निर्देशिका प्रविष्टि के बारे में मेटाडेटा प्राप्त करने के लिए कॉल करना, जैसे कि यह एक निर्देशिका है।
# 3 अब तक का सबसे महंगा है, क्योंकि इसमें प्रत्येक फ़ाइल के लिए एक इनलोड लोड करने की आवश्यकता होती है। तुलना में # 1 के लिए आवश्यक सभी फ़ाइल नाम कॉम्पैक्ट रूप से कुछ ब्लॉकों में संग्रहीत किए जाते हैं। # 2 कुछ CPU समय बर्बाद करता है लेकिन यह अक्सर एक सौदा ब्रेकर नहीं होता है।
यदि फ़ाइल नामों में कोई नई सूची नहीं है, तो एक साधारण ls -A | wc -l
आपको बताता है कि निर्देशिका में कितनी फाइलें हैं। सावधान रहें कि यदि आप के लिए एक उपनाम है ls
, इस के लिए एक कॉल गति प्रदान कर सकते stat
हैं (जैसे ls --color
या ls -F
फ़ाइल प्रकार है, जो करने के लिए एक फोन की आवश्यकता है पता करने की जरूरत stat
है, तो कमांड लाइन से,) फोन command ls -A | wc -l
या \ls -A | wc -l
किसी अन्य नाम से बचने के लिए।
यदि फ़ाइल के नाम में नई सूचियाँ हैं, तो नई सूचियाँ सूचीबद्ध हैं या नहीं, यह यूनिक्स संस्करण पर निर्भर करता है। GNU कोरयूटिल्स और बिजीबॉक्स डिफॉल्ट ?
नई लाइन के लिए डिफॉल्ट करते हैं, इसलिए वे सुरक्षित हैं।
ls -f
उन्हें (# 2) सॉर्ट किए बिना प्रविष्टियों को सूचीबद्ध करने के लिए कॉल करें। यह स्वचालित रूप से -a
(कम से कम आधुनिक प्रणालियों पर) चालू होता है। -f
विकल्प POSIX में लेकिन वैकल्पिक स्थिति के साथ है, अधिकांश कार्यान्वयन इसका समर्थन करते हैं, लेकिन व्यस्त बॉक्स नहीं। यह विकल्प -q
गैर-मुद्रण योग्य वर्णों को प्रतिस्थापित करता है ?
, जिनमें नई लिस्ट शामिल हैं ; यह पॉसिक्स है, लेकिन बिजीबॉक्स द्वारा समर्थित नहीं है, इसलिए इसे छोड़ दें यदि आपको उन फ़ाइलों को ओवरकाउंट करने की कीमत पर बिजीबॉक्स समर्थन की आवश्यकता है जिनके नाम में एक नई लाइन वर्ण है।
यदि निर्देशिका में कोई उपनिर्देशिका नहीं है, तो इसके प्रविष्टियों पर अधिकांश संस्करण find
कॉल नहीं करेंगे stat
(लीफ डाइरेक्टरी ऑप्टिमाइज़ेशन: एक निर्देशिका जिसमें 2 की लिंक गणना है, उपनिर्देशिकाएँ नहीं हो सकती हैं, इसलिए find
जब तक कि प्रविष्टियों की मेटाडेटा देखने की आवश्यकता न हो, शर्त ऐसी है कि इसकी -type
आवश्यकता है)। इसलिए find . | wc -l
एक निर्देशिका में फ़ाइलों को गिनने का एक पोर्टेबल, तेज़ तरीका है बशर्ते कि निर्देशिका में कोई उपनिर्देशिका न हो और कोई फ़ाइल नाम में कोई नई पंक्ति न हो।
यदि निर्देशिका में कोई उपनिर्देशिका नहीं है, लेकिन फ़ाइल नामों में नई सूची हो सकती है, तो इनमें से एक को आज़माएं (यदि यह समर्थित है, तो दूसरा तेज़ होना चाहिए, लेकिन ऐसा नहीं हो सकता है)।
find -print0 | tr -dc \\0 | wc -c
find -printf a | wc -c
दूसरी ओर, find
यदि निर्देशिका में उपनिर्देशिका है , तो इसका उपयोग न करें : यहां तक कि हर प्रविष्टि पर find . -maxdepth 1
कॉल करें stat
(कम से कम जीएनयू ढूंढें और बिजीबॉक्स ढूंढें)। आप (# 2) सॉर्ट करने से बचते हैं लेकिन आप इनकोड लुकअप (# 3) की कीमत चुकाते हैं जो प्रदर्शन को मारता है।
बाहरी उपकरणों के बिना शेल में, आप वर्तमान निर्देशिका में फ़ाइलों को गिन सकते हैं set -- *; echo $#
। यह डॉट फाइलें (जिनके नाम से शुरू होती है .
) फाइलें और खाली निर्देशिका में 0 के बजाय 1 रिपोर्ट करता है। यह छोटी निर्देशिकाओं में फ़ाइलों को गिनने का सबसे तेज़ तरीका है, क्योंकि इसके लिए बाहरी कार्यक्रम शुरू करने की आवश्यकता नहीं है, लेकिन (zsh को छोड़कर) सॉर्टिंग चरण (# 2) के कारण बड़ी निर्देशिकाओं के लिए समय बर्बाद करता है।
बैश में, यह वर्तमान निर्देशिका में फ़ाइलों को गिनने का एक विश्वसनीय तरीका है:
shopt -s dotglob nullglob
a=(*)
echo ${#a[@]}
Ksh93 में, यह वर्तमान निर्देशिका में फ़ाइलों को गिनने का एक विश्वसनीय तरीका है:
FIGNORE='@(.|..)'
a=(~(N)*)
echo ${#a[@]}
Zsh में, यह वर्तमान निर्देशिका में फ़ाइलों को गिनने का एक विश्वसनीय तरीका है:
a=(*(DNoN))
echo $#a
यदि आपके पास mark_dirs
विकल्प सेट है, तो इसे बंद करना सुनिश्चित करें a=(*(DNoN^M))
:।
किसी भी POSIX शेल में, यह वर्तमान निर्देशिका में फ़ाइलों को गिनने का एक विश्वसनीय तरीका है:
total=0
set -- *
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
set -- .[!.]*
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
set -- ..?*
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
echo "$total"
ये सभी विधियाँ फ़ाइल नामों को क्रमबद्ध करती हैं, केवल zsh को छोड़कर।
ls -l|wc -l
ls -l
उत्पादन की पहली पंक्ति में कुल ब्लॉकों के कारण एक-एक करके बंद हो जाएगा