एक निश्चित निर्देशिका में कितनी फाइलें और निर्देशिकाएं खोजने के लिए wc और पाइपिंग का उपयोग करें?


10

मैं शब्द काउंटर ( wc) और पाइपिंग का उपयोग करके गिन सकता हूं कि निर्देशिका में कितनी फाइलें या निर्देशिकाएं हैं /usr/bin?


यह होमवर्क ?? मदद के लिए पूछना ठीक है, बस इसे इस तरह से पहचानें, यदि यह है।
SLM

हाँ, यह है लेकिन मैं यहाँ पोस्ट करता हूँ कि लिनक्स पर नया होने के बाद से कैसे कुछ हासिल किया जा सकता है और यह बहुत जटिल हो सकता है। और मैं पहले से ही इस आदेश के साथ ऊपर दिए गए प्रश्न को हल करता हूं
कैश

ls / bin / usr / बिन | सॉर्ट | यूनीक | wc -
कैश

एन पी। मदद के लिए पूछना पूरी तरह से ठीक है! बस इसे लेबल करें ताकि लोग जानते हैं, यहां हर कोई आमतौर पर उन लोगों की मदद करने में खुश है जो यूनिक्स के बारीकियों को सीखने की कोशिश कर रहे हैं।
स्लम sl

जवाबों:


13

एक तरीका यह होगा lsकि हम फाइलों की एक सूची दें, लेकिन हम चाहते हैं कि यह सूची केवल 1 फ़ाइल या निर्देशिका प्रति लाइन दिखाने की गारंटी हो। -1स्विच हमारे लिए यह कर देगा।

$ ls -1
dir1
dir2
dir3
fileA
fileB
fileC

उदाहरण

एक खाली निर्देशिका में उपरोक्त नमूना डेटा बनाएँ।

$ mkdir dir{1..3}
$ touch file{A..C}

इसे जाँचे:

$ ls
dir1  dir2  dir3  fileA  fileB  fileC

अब गणना करने के लिए आप wc -lलाइनों की संख्या की गणना करने के लिए उपयोग कर सकते हैं , जो ls -1आउटपुट में एक फ़ाइल या निर्देशिका के अनुरूप है ।

$ ls -1 | wc -l
6

(ध्यान दें कि इसमें छिपी हुई फाइलें शामिल नहीं हैं)

फाइलों या निर्देशिकाओं की गणना, बस एक साथ नहीं

फ़ाइलों या निर्देशिकाओं की गणना करने के लिए आपको अपनी रणनीति को थोड़ा बदलना होगा। इस मामले में मैं इसका उपयोग करूंगा ls -lक्योंकि यह दिखाता है कि निर्देशिका क्या है और आ फाइल क्या है।

उदाहरण

$ ls -l
total 12
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir1
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir2
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir3
-rw-rw-r-- 1 saml saml    0 Nov 16 09:49 fileA
-rw-rw-r-- 1 saml saml    0 Nov 16 09:49 fileB
-rw-rw-r-- 1 saml saml    0 Nov 16 09:49 fileC

फिर हम grepनिर्देशिकाओं को फ़िल्टर करने के लिए उपयोग कर सकते हैं या नहीं-निर्देशिकाओं जैसे:

# directories
$ ls -l | grep "^d"
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir1
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir2
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir3

# regular files
$ ls -l | grep "^-"
-rw-rw-r-- 1 saml saml    0 Nov 16 09:49 fileA
-rw-rw-r-- 1 saml saml    0 Nov 16 09:49 fileB
-rw-rw-r-- 1 saml saml    0 Nov 16 09:49 fileC

अब बस wc -lफिर से ऊपर की गिनती का उपयोग करें:

# directories
$ ls -l | grep "^d" | wc -l
3

# regular files
$ ls -l | grep "^-" | wc -l
3

हालांकि, आप बच सकते हैं wcपूरी तरह उपयोग करते हैं, और grepके -cविकल्प:

$ ls -l | grep -c '^d'

(फिर से, छिपी हुई फाइलें शामिल नहीं हैं। ध्यान दें कि निर्देशिका और नियमित दो प्रकार की फाइलें हैं। कई और नाम हैं जैसे पाइप, प्रतीकात्मक लिंक, डिवाइस, सॉकेट ...)।

प्रत्यावर्तन

यदि आपको फ़ाइलों और निर्देशिकाओं को पुनरावर्ती खोजने की आवश्यकता है, /usr/binतो आप संभवतः रणनीति को पूरी तरह से बदलना और किसी अन्य उपकरण का उपयोग करना चाहेंगे find

उदाहरण

$ find /usr/bin | wc -l
4632

(हालांकि ऊपर /usr/binही गिनती में शामिल है)

वही तकनीक जो मैंने ऊपर इस्तेमाल की है, उसे lsकुछ समान करने के लिए नियोजित उपयोग किया जा सकता है, लेकिन lsआमतौर पर आउटपुट को पार्स करने के लिए एक अच्छा उपकरण नहीं है। findदूसरी ओर इस के लिए बनाया गया था, और फ़ाइलों या निर्देशिकाओं को खोजने के लिए स्विच प्रदान करता है।

# find files
$ find /usr/bin -type f

# find directories
$ find /usr/bin -type d

(ध्यान दें कि इस बार, findछिपी हुई फ़ाइलों (छोड़कर .और ..) सहित है ।

नई-पंक्तियों?

मैंने कभी नहीं सोचा है कि फ़ाइल नाम या निर्देशिका नाम बनाते समय एक नया वर्ण का उपयोग करने के लिए एक कानूनी चरित्र क्यों है। इसलिए उपरोक्त विधियों का उपयोग करने के बारे में चर्चा की गई है wcऔर lsवे इनसे जूझेंगे नहीं, इसलिए इन्हें ध्यान में रखकर उपयोग करें।

उदाहरण

एक निर्देशिका बनाएँ और newlines के साथ फ़ाइल नाम।

$ mkdir $'dir4\n5'
$ touch $'fileD\nE'

ls उन्हें सही ढंग से दिखाता है:

$ ls -1
dir1
dir2
dir3
dir4?5
fileA
fileB
fileC
fileD?E

लेकिन wcउन निर्देशिकाओं और फाइलों को गिनता है जिनमें 2 आइटम के रूप में नई-नई चीजें होती हैं, एक नहीं।

$ ls -1 | wc -l
10

इसके आसपास पाने के लिए एक विधि, यदि GNU कार्यान्वयन का findउपयोग findप्रत्येक फ़ाइल के स्थान पर कुछ और प्रिंट करने की क्षमता का उपयोग करने के लिए होता है, जो इसे ढूंढता है और फिर इसके बजाय गिनता है।

उदाहरण

$ find . -printf . | wc -c
9

यहाँ हम वर्तमान निर्देशिका (सिवाय में हैं खोजने के लिए सब कुछ ..है), और एक बिंदु (मुद्रण .) प्रत्येक के लिए, और उसके बाद का उपयोग कर डॉट्स गिनती wcलाइनों के बजाय बाइट्स गिनती करने के लिए की क्षमता, wc -c

संदर्भ


जबकि फाइलें /usr/binसभी में अच्छी तरह से स्वरूपित होने जा रही हैं (और इसमें रिक्त स्थान भी नहीं होंगे, इसलिए तकनीकी रूप से आप बस भी कर सकते हैं echo * | wc -w), यह ध्यान देने योग्य है कि ये सभी नए नाम वाले फाइलनाम पर टूटेंगे।
15

@evilsoup - नहीं मुझे विश्वास नहीं है ls -lया ls -1बी / सी को तोड़ देगा हम शब्दों की नहीं, लाइनों की गिनती कर रहे हैं! findतोड़ सकता है, लेकिन फिर, हम लाइनों गिनती कर रहे हैं नहीं शब्द।
SLM

मेरा मतलब है कि यह होगा (मुझे लगता है, मैं अभी विंडोज पर हूं, इसलिए मैं परीक्षण नहीं कर सकता) अगर फाइल में नई सुर्खियां होती हैं तो मैं टूट जाता हूं । तो touch $'foo\nbar'एक खाली निर्देशिका के भीतर आपके आदेशों में से एक (कहते हैं ls -1 | wc -l) एक के बजाय दो फ़ाइलों की रिपोर्ट करेगा - क्योंकि एक फ़ाइल दो पंक्तियों है जहाँ तक wcचिंतित है। जब तक lsकुछ अन्य चरित्रों के साथ नई कहानियों की जगह नहीं ली जाती (मुझे नहीं लगता कि यह करता है, लेकिन फिर से मैं अभी परीक्षण करने की स्थिति में नहीं हूं)।
evilsoup

@evilsoup - सही, न्यूलाइन चार। एक कानूनी चर है। फ़ाइल नामों के लिए, और विधियाँ उन प्रकार के फ़ाइलनामों के साथ सही तरीके से प्रतिस्पर्धा करने में सक्षम नहीं होंगी।
SLM

@StephaneChazelas - wc -cपीरियड्स गिनते समय एक मुद्दा है?
SLM

5

यदि आप जीएनयू के साथ, कुछ dir के तहत प्रत्येक प्रकार की फ़ाइल की संख्या का ब्रेक डाउन प्राप्त करना चाहते हैं find, तो आप निम्न कार्य कर सकते हैं:

find /some/dir/. ! -name . -printf '%y\n' | sort | uniq -c | sed '
  s/f/regular files/;t
  s/d/directories/;t
  s/l/symbolic links/;t
  s/s/Unix domain sockets/;t
  s/b/block devices/;t
  s/c/character devices/;t
  s/p/FIFOs/;t
  s/D/Doors/;t
  s/n/network special files/;t
  s/.$/others (&)/'

पर /usr/binअपने सिस्टम पर, कि देता है:

   3727 regular files
    710 symbolic links

पर /dev:

     83 block devices
    203 character devices
     31 directories
    426 symbolic links
      1 FIFOs
      1 Unix domain sockets

सीमलिंक के लिए, यदि आप उन्हें उस फ़ाइल के प्रकार के रूप में गिनते हैं symbolic links, जिसके बजाय वे इंगित करते हैं , तो आप इसे बदल सकते हैं:

find /some/dir/. ! -name . -printf '%Y\n' | sort | uniq -c | sed '
  s/f/regular files/;t
  s/d/directories/;t
  s/N/broken symbolic links/;t
  s/s/Unix domain sockets/;t
  s/b/block devices/;t
  s/c/character devices/;t
  s/p/FIFOs/;t
  s/D/Doors/;t
  s/n/network special files/;t
  s/.$/others (&)/'

जो अब मेरे लिए देता है /usr/bin:

      1 directories
   4434 regular files
      2 broken symbolic links

(एक टूटी हुई सिमलिंक एक फाइल के लिए एक सिमलिंक है जिसके लिए findया तो प्रकार का निर्धारण नहीं किया जा सकता है क्योंकि फ़ाइल मौजूद नहीं है, या एक निर्देशिका में है जिसके लिए आपके पास एक्सेस नहीं है या फ़ाइल के पथ के संकल्प में एक लूप है। (मेरे मामले में, वे 2 जहाँ अब गई फाइलों के लिए सहानुभूति रखते हैं)।

उन गिनती में से कोई भी .और ..। यदि आप चाहते थे उन्हें शामिल (? क्यों तुम करोगी), वहाँ के साथ कोई दूसरा रास्ता नहीं है findकी तुलना में यह मान वे हर निर्देशिका के लिए वहाँ हो और उन्हें व्यवस्थित गिनती:

find /some/dir/. -printf '%y\n' \( -name . -printf 'd\n' -o \
  -type d -printf 'd\nd\n' \)  | sort | uniq -c | sed '
  s/f/regular files/;t
  s/d/directories/;t
  s/l/symbolic links/;t
  s/s/Unix domain sockets/;t
  s/b/block devices/;t
  s/c/character devices/;t
  s/p/FIFOs/;t
  s/D/Doors/;t
  s/n/network special files/;t
  s/.$/others (&)/'

जो तब मेरे पर देता है /usr/bin:

      2 directories
   3727 regular files
    710 symbolic links

यदि आपके पास GNU तक पहुँच नहीं है find, तो आप पहले वाले को फिर से लिख सकते हैं:

find /some/dir/. ! -name . \( \
  -type f -exec printf '%.0sregular files\n' {} + -o \
  -type d -exec printf '%.0sdirectories\n' {} + -o \
  -type l -exec printf '%.0ssymbolic links\n' {} + -o \
  -type s -exec printf '%.0sUnix domain sockets\n' {} + -o \
  -type b -exec printf '%.0sblock devices\n' {} + -o \
  -type c -exec printf '%.0scharacter devices\n' {} + -o \
  -type p -exec printf '%.0sFIFOs\n' {} + -o \
  -exec printf '%.0sothers\n' {} + \) | sort | uniq -c

अब, कड़ाई से बोलते हुए, हम फाइलों को नहीं बल्कि निर्देशिका प्रविष्टियों को गिन रहे हैं । एक निर्देशिका की तरह /usr/binआम तौर पर कई प्रविष्टियाँ होती हैं जो एक ही फ़ाइल को इंगित करती हैं। उदाहरण के लिए, यहाँ, मेरे पास है:

$ ls -lid /usr/bin/{nvi,nview,nex}
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nex
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nvi
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nview

एक ही फ़ाइल में 3 निर्देशिका प्रविष्टियाँ (उर्फ फ़ाइल नाम उर्फ ​​हार्ड लिंक) हैं (एक इनोड 672252 के साथ। निर्देशिका प्रविष्टियों के बजाय फ़ाइलों को गिनने के लिए और GNU findऔर GNU के साथ) uniq(अनदेखी .और ..फ़ाइलें जो वैसे भी अन्य निर्देशिकाओं के लिए कड़ी हैं):

find /some/dir/. ! -name . -printf '%y\t%D:%i\n' |
  sort -u |
  cut -f1 |
  uniq -c |
  sed '
    s/f/regular files/;t
    s/d/directories/;t
    s/l/symbolic links/;t
    s/s/Unix domain sockets/;t
    s/b/block devices/;t
    s/c/character devices/;t
    s/p/FIFOs/;t
    s/d/Doors/;t
    s/n/network special files/;t
    s/.$/others (&)/'

मेरे पर /usr/bin, जो देता है:

   3711 regular files
    710 symbolic links

0

आपने यह नहीं कहा है कि क्या आप सभी फाइल को / usr / bin को पुनरावर्ती या सिर्फ पहले स्तर के तहत चाहते हैं। इसके अलावा, आप उन शब्दों को कैसे प्राप्त करेंगे जो आप गिन रहे हैं? पता लगाने का सामान्य तरीका wc में ढूंढना है। इस तरह: Find / usr / bin | wc -l फाइंड वहां मौजूद सभी चीजों, निर्देशिकाओं और फाइलों को सूचीबद्ध करेगा। Wc -l खोज आउटपुट में सभी लाइनों की गणना करेगा। क्या यह एक क्लास असाइनमेंट है? यह ठीक है अगर यह है, लेकिन मैं सोच रहा था कि आपको इस जानकारी की आवश्यकता क्यों थी ताकि मैं प्रतिक्रिया को अधिक ध्यान से दर्जी कर सकूं। कृपया मुझे बताएं कि क्या आपको और अधिक की आवश्यकता है। कोस्टा


0

बैश में, बाहरी उपकरणों के बिना।

cd dir/ || exit; shopt -s nullglob; shopt -s dotglob; count=(*); echo "${#count}"

बैश में, बाहरी उपकरणों और पुनरावृत्ति के बिना।

shopt -s globstar; shopt -s dotglob 
for dir in **/*/; do 
  unset d f
  for files in "$dir"*; do 
    [[ -f $files ]] && ((++f))
    [[ -d $files ]] && ((++d))
  done; 
  printf '%s\n' "$dir -  files: ${f:-0} - directories: ${d:-0}"
done

ध्यान दें कि दूसरे का उपयोग करते समय सहानुभूति का पालन होता है (और नियमित फ़ाइलों के रूप में नियमित फ़ाइलों के लिए सहानुभूति की गणना करता है, और डायर के रूप में डर्म्स के लिए सहानुभूति रखता है), वर्तमान निर्देशिका में फ़ाइलों और निर्देशिकाओं की गणना नहीं करेगा और न .ही ..प्रविष्टियों की गणना करेगा । आप फ़ाइल बनाम नियमित फ़ाइल को तोड़ना चाह सकते हैं।
स्टीफन चेजलस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.