2010-09-13 15 views
23

क्या सूची में बिना ओ (1) (स्वतंत्र रूप से फ़ाइलों की संख्या के) निर्देशिका में फ़ाइलों की संख्या (यानी तात्कालिक बच्चों) की फ़ाइलों की गणना करने के लिए लिनक्स में कोई विधि है? निर्देशिका पहले? यदि ओ (1) नहीं है, तो क्या कोई उचित तरीका है?निर्देशिका में फ़ाइलों की संख्या

मैं ls | wc -l के विकल्प के लिए खोज रहा हूं।

+0

'एलएस | wc -l' ओ (1) नहीं है? – halfdan

+4

एलएस | wc -l ls को सभी फ़ाइलों पर एक opendir(), readdir() और शायद एक stat() करने के लिए कारण होगा। यह आम तौर पर कम से कम ओ (एन) होगा। – MarkR

+1

@halfdan: ls सभी फ़ाइलों को आउटपुट करता है, इसलिए यह ओ (एन) – yassin

उत्तर

33

readdir उतना महंगा नहीं है जितना आप सोच सकते हैं। नाटक प्रत्येक फ़ाइल को statinging से बचने के लिए है, और (वैकल्पिक रूप से) एलएस के आउटपुट सॉर्टिंग।

/bin/ls -1U | wc -l

अपने खोल में उपनाम से बचा जाता है, उत्पादन को सॉर्ट नहीं है, और सूचियों 1 फ़ाइल-प्रति-लाइन (सख्ती से आवश्यक नहीं जब WC में उत्पादन पाइप)।

मूल प्रश्न को फिर से लिखा जा सकता है "क्या निर्देशिका की डेटा संरचना प्रविष्टियों की संख्या की गणना करता है?", जिस पर उत्तर नहीं है। Readdir (2)/getdents (2) की तुलना में फ़ाइलों की गिनती का एक और अधिक प्रभावी तरीका नहीं है।

+0

उपनाम से बचने के लिए, आप कर सकते हैं '\ ls' भी कहें। जांचें [\ curl ... | bash ... के लिए स्लैश क्या है?] (http://stackoverflow.com/a/15951871/1983854) – fedorqui

1

जहां तक ​​मुझे पता है, कोई बेहतर विकल्प नहीं है। यह जानकारी इस प्रश्न के विषय-वस्तु हो सकती है और आप पहले से ही यह जान सकते हैं कि लिनक्स (सामान्य रूप से यूनिक्स के तहत) निर्देशिकाएं केवल विशेष फ़ाइल हैं जिनमें अन्य फ़ाइलों की सूची शामिल है (मैं समझता हूं कि सटीक विवरण विशिष्ट फ़ाइल पर निर्भर होंगे प्रणाली लेकिन यह सामान्य विचार है)। और पूरी सूची को घुमाने के बिना प्रविष्टियों की कुल संख्या को खोजने के लिए कोई कॉल नहीं है। अगर मैं गलत हूं तो कृपया मुझे सही करें।

10

किसी दिए गए निर्देशिका की statding (stat (1) या stat (2)) द्वारा पूरी सूची को घुमाने के बिना किसी दिए गए निर्देशिका की उप-निर्देशिकाओं की संख्या प्राप्त हो सकती है और उस निर्देशिका के लिंक को देखकर। एन बाल निर्देशिकाओं के साथ दी गई निर्देशिका में एन + 2 की लिंक गिनती होगी, प्रत्येक उपनिर्देशिका के ".." प्रविष्टि के लिए एक लिंक, साथ ही "।" और दी गई निर्देशिका की ".." प्रविष्टियां।

हालांकि कोई भी पूरी सूची को ट्रैक किए बिना सभी फ़ाइलों (चाहे नियमित फाइलें या उपनिर्देशिका) की संख्या प्राप्त नहीं कर सकता - यह सही है।

"/ bin/ls -1U" कमांड को सभी प्रविष्टियां नहीं मिलेंगी। यह केवल उन निर्देशिका प्रविष्टियों को प्राप्त करेगा जो डॉट (।) वर्ण से प्रारंभ नहीं होते हैं। उदाहरण के लिए, यह कई लॉगिन $ HOME निर्देशिकाओं में मिली ".profile" फ़ाइल की गणना नहीं करेगा।

कोई भी "/ bin/ls -f" कमांड या "/ bin/ls -Ua" कमांड का उपयोग इस प्रकार से बचने और सभी प्रविष्टियों को प्राप्त करने के लिए कर सकता है।

दुर्भाग्य से आपके उद्देश्यों के लिए, या तो "/ bin/ls -f" कमांड या "/ bin/ls -Ua" कमांड भी "।" और ".." प्रविष्टियां जो प्रत्येक निर्देशिका में हैं। "/ Bin पर

expr `/bin/ls -f | wc -l` - 2  # Those are back ticks, not single quotes. 

--format = एकल-स्तंभ (-1) विकल्प आवश्यक नहीं है: आप गिनती से 2 घटाना जैसे कि निम्न में के रूप में इन दो प्रविष्टियों, गिनती से बचने के लिए होगा/ls -Ua "आदेश" ls "आउटपुट को पाइप करते समय, इस मामले में" wc "के रूप में। यदि आउटपुट टर्मिनल नहीं है तो "ls" कमांड स्वचालित रूप से एक ही कॉलम में अपना आउटपुट लिख देगा।

+0

सहमत है कि 'ls -f'' ls -1U' से बेहतर है (मुझे लगता है कि '-f' इस तरह के लिए है पाइपिंग), लेकिन मैं चाहता हूं कि 'एलएस' के पास प्रत्येक फ़ाइल नाम को एक न्यूलाइन के बजाय एनयूएल चरित्र के साथ समाप्त करने का विकल्प था। लिनक्स पर – musiphil

+0

: '-b, --escape प्रिंट सी-शैली नोंग्राफिक वर्णों के लिए निकलती है; जो एम्बेडेड न्यूलाइन को '\ n' के रूप में मुद्रित करेगा। – blalor

-1

उपयोग ls -1 | wc -l

+0

ls -l आपको कुल ब्लॉक की एक अतिरिक्त पंक्ति देगा जो गिनती करते समय एक अतिरिक्त पंक्ति होगी। एलएस -1 नहीं है। –

+1

@ वेंकटरामेमकोमोजो, ए) आप यह नहीं समझा रहे हैं कि यह 'एलएस से बेहतर क्यों माना जाता है। wc -l' और बी) यह नहीं है। –

2

मैंने इस कमांड का उपयोग किया .. एक आकर्षण की तरह काम करता है ... केवल maxdepth को बदलने के लिए ..कि उप निर्देशिका

find * -maxdepth 0 -type d -exec sh -c "echo -n {} ' ' ; ls -lR {} | wc -l" \; 
3

ls के लिए -U विकल्प POSIX में नहीं है, और में है ओएस एक्स के ls यह जीएनयू ls, जो है कि यह -t और -l उपयोग सृजन बार के बजाय बनाता है से एक अलग अर्थ नहीं है संशोधन के समय -f एक एक्सएसआई एक्सटेंशन के रूप में POSIX में है। जीएनयू ls का मैनुअल -fdo not sort, enable -aU, disable -ls --color और -Udo not sort; list entries in directory order के रूप में वर्णित करता है।

POSIX का वर्णन करता है -f इस तरह:

फोर्स प्रत्येक तर्क एक निर्देशिका के रूप में व्याख्या और नाम प्रत्येक स्लॉट में पाया सूची किया जाना है। यह विकल्प -l, -t, -s, और -r बंद कर देगा, और -a चालू करेगा; ऑर्डर वह क्रम है जिसमें निर्देशिका में प्रविष्टियां दिखाई देती हैं।

ls|wc -l जैसे कमांड गलत परिणाम देते हैं जब फ़ाइल नामों में न्यूलाइन होती है।

zsh में आप कुछ इस तरह कर सकते हैं:

a=(*(DN));echo ${#a} 

D (glob_dots) फ़ाइलें जिसका नाम अवधि और N (null_glob) के साथ शुरू होता शामिल का कारण बनता है नहीं करने के लिए आदेश में एक खाली निर्देशिका में एक त्रुटि में परिणाम ।

या बैश में एक ही:

shopt -s dotglob nullglob;a=(*);echo ${#a[@]} 

IFS ASCII अंक हैं, तो ${#a[@]} को दोहरे उद्धरण चिह्नों जोड़ें। यह सुनिश्चित करने के लिए कि failglob अनसेट है, shopt -u failglob जोड़ें।

एक पोर्टेबल विकल्प find उपयोग करने के लिए है:

find . ! -name . -prune|grep -c/

grep -c /wc -l साथ बदला जा सकता है, तो फ़ाइल नाम नई पंक्तियां शामिल नहीं है। ! -name . -prune-mindepth 1 -maxdepth 1 के लिए एक पोर्टेबल विकल्प है।

या यहाँ एक और विकल्प है कि आम तौर पर फ़ाइलें जिसका नाम अवधि के साथ शुरू होता है शामिल नहीं है:

set -- *;[ -e "$1" ]&&echo "$#" 

आदेश ऊपर तथापि फ़ाइलें जिसका नाम अवधि के साथ शुरू होता है शामिल है जब पार्टी में dotglob या glob_dots जैसा कोई विकल्प zsh में सेट है। जब * कोई फ़ाइल मेल नहीं खाता है, तो आदेश डिफ़ॉल्ट सेटिंग्स के साथ zsh में त्रुटि में परिणाम देता है।

+0

आपके उत्तर से, मैंने इसे बैश के लिए एक साथ रखा: '(अनसेट IFS; shopt -s dotglob nullglob; shopt -u failglob; a = (*); echo $ {# a [@]}) - माता-पिता को नोट करें, जो एक सबहेल में निष्पादन का कारण बनता है, इस प्रकार वर्तमान शैल के विकल्पों और आईएफएस मूल्य को संरक्षित करता है। – ThomasR

1

मुझे लगता है कि आप find उपयोग करते हुए इस पर अधिक नियंत्रण है कर सकते हैं:

find <path> -maxdepth 1 -type f -printf "." | wc -c 
  • find -maxdepth 1 फ़ाइलों के पदानुक्रम में गहरी नहीं जाना होगा।
  • -type f केवल फ़ाइलों को फ़िल्टर करने की अनुमति देता है। इसी प्रकार, आप निर्देशिकाओं के लिए -type d का उपयोग कर सकते हैं।
  • -printf "." प्रत्येक मैच के लिए एक बिंदु मुद्रित करता है।
  • wc -c अक्षरों की गणना करता है, इसलिए यह print द्वारा बनाए गए बिंदुओं की गणना करता है ... जिसका अर्थ यह है कि दिए गए पथ में कितनी फ़ाइलें मौजूद हैं।