प्रत्येक निर्देशिका में फ़ाइलों की संख्या की गणना कैसे करें?


104

मैं सभी निर्देशिकाओं को सूचीबद्ध करने में सक्षम हूं

find ./ -type d

मैंने प्रत्येक निर्देशिका की सामग्री को सूचीबद्ध करने और निम्नलिखित आदेश का उपयोग करके प्रत्येक निर्देशिका में फ़ाइलों की संख्या गिनने का प्रयास किया

find ./ -type d | xargs ls -l | wc -l

लेकिन इससे कुल पंक्तियों की संख्या वापस आ गई

find ./ -type d | xargs ls -l

क्या कोई तरीका है जिससे मैं प्रत्येक निर्देशिका में फ़ाइलों की संख्या गिन सकता हूं?


क्या आप सीधे उप-निर्देशिकाओं में से प्रत्येक में फ़ाइलों की संख्या की गणना करने का एक तरीका खोज रहे हैं ./?
Tuxdude

5
यह एक ऑफ-टॉपिक सवाल कैसे है ?? मैं करीबी मतदाताओं की टिप्पणियों को तर्क के साथ देखना चाहूंगा! अगर यह ऑफ-टॉपिक है तो यह कहां से आता है? सुपर यूजर? मुझे ऐसा नहीं लगता ..
शिशुप्रो

6
शेल-स्क्रिप्ट, बैच-स्क्रिप्ट प्रोग्रामिंग दायरे में हैं!
शिशुप्रधान अरविंद '

मैं पाइथोनिक समाधान पोस्ट करने वाला था तब मैंने देखा कि प्रश्न बंद है।
15:20 बजे अनातोली टेकटोनिक

इसे फिर से खोलने के लिए मतदान किया गया। ऐसे अन्य उत्तर हो सकते हैं जो कई स्थितियों में उपयोगी हो सकते हैं (स्क्रिप्ट प्रोग्रामिंग सहित, यही कारण है कि मैं इस प्रश्न पर पहुंचा हूं)।
लेप जुले

जवाबों:


110

मान लें कि आपको GNU मिल गया है, तो इसे निर्देशिकाओं को खोजने दें और बाकी चीजों को करने दें:

find . -type d -print0 | while read -d '' -r dir; do
    files=("$dir"/*)
    printf "%5d files in directory %s\n" "${#files[@]}" "$dir"
done

2
ऊपर से इसका सिर्फ एक अलग प्रकार का संस्करण है, इसलिए: (संकेत: इसका नाम और इसके सीएसवी में क्रमबद्ध रूप से) x के लिए find . -maxdepth 1 -type d | sort; वाई = find $x | wc -l; इको $ x, $ y; किया
pcarvalho

5
महान एक! इसे एक ही पंक्ति में find . -type d -print0 | while read -d '' -r dir; do files=("$dir"/*); printf "%5d files in directory %s\n" "${#files[@]}" "$dir"; done
रखना

13
मुझे प्रत्येक उपनिर्देशिका में सभी फाइलों (पुनरावर्ती गणना) की संख्या प्राप्त करने की आवश्यकता थी। यह संशोधन आपको यह बताता है कि: find . -maxdepth 1 -type d -print0 | while read -d '' -r dir; do num=$(find $dir -ls | wc -l); printf "%5d files in directory %s\n" "$num" "$dir"; done
OmidS

1
@ कोरी निम्नलिखित करेंगे:find . -maxdepth 1 -type d -print0 | while read -d '' -r dir; do num=$(find "$dir" -ls | wc -l); printf "%5d files in directory %s\n" "$num" "$dir"; done | sort -rn -k1
ओमिड्स

1
@ ओमीडस ग्रेट ऑनलाइनर, लेकिन व्हाट्सएप के $dirसाथ डायर नामों को सही ढंग से संभालने के लिए आपकी पहली टिप्पणी में उद्धरण के अंदर होना चाहिए। :find . -maxdepth 1 -type d -print0 | while read -d '' -r dir; do num=$(find "$dir" -ls | wc -l); printf "%5d files in directory %s\n" "$num" "$dir"; done
राडेक डेनिलुक

183

यह वर्तमान निर्देशिका स्तर के लिए प्रति निर्देशिका फ़ाइल गणना को प्रिंट करता है:

du -a | cut -d/ -f2 | sort | uniq -c | sort -nr

9
यदि कोई शीर्ष स्तर निर्देशिकाओं में फ़ाइलों की संख्या को पुनरावर्ती रूप से सूचीबद्ध करना चाहता है, तो सबसे अच्छा (और सबसे सुरुचिपूर्ण) समाधान।
itoctopus

13
इसकी दो समस्याएं हैं: यह प्रति डायरेक्टरी में एक फ़ाइल को मायने रखता है, जो वास्तव में अधिक है और यह एक बेकार लाइन देता है जिसमें "1 आकार " के रूप में वर्तमान निर्देशिका का आकार होता है । दोनों के साथ तय किया जा सकता है du -a | sed '/.*\.\/.*\/.*/!d' | cut -d/ -f2 | sort | uniq -c। जोड़े | sort -nrगिनती के बजाय निर्देशिका नाम से तरह करने के लिए।
मिठाई

3
मैं यह बताना चाहता हूं कि यह OSX में भी काम करता है। (बस OSX खोल में लिनक्स सलाह कॉपी-पेस्ट करने से काम नहीं चलता।)
पिस्तोस

2
यह du -a द्वारा अनावश्यक आकार प्राप्त करता है। बेहतर तरीका खोज कमांड का उपयोग कर रहा है। लेकिन मुख्य विचार बिल्कुल वैसा ही है :)
ज़निक

5
खोजो। -प्रकार f | cut -d / -f2 | सॉर्ट | uniq -c | सॉर्ट -nr # मिठाई द्वारा बताई गई समस्याओं को ठीक करता है
jcomeau_ictx

28
find . -type f | cut -d/ -f2 | sort | uniq -c
  • find. -type f प्रकार फ़ाइल के सभी आइटम खोजने के लिए
  • cut -d/ -f2 उनके विशिष्ट फ़ोल्डर को काटने के लिए
  • sort फ़ोल्डरनाम की सूची को सॉर्ट करने के लिए
  • uniq -c प्रत्येक फ़ोल्डरनाम को गिने जाने की संख्या को वापस करने के लिए

8
यह स्वीकृत उत्तर की तुलना में बहुत बेहतर है, क्योंकि आपको शीर्ष-स्तरीय निर्देशिकाओं का सारांश मिलता है!
जेसन फ्लॉइड

3
यह स्वीकृत उत्तर होना चाहिए। सरल और बोधगम्य।
xssChauhan

1
सबसे अच्छा जवाब जो स्वीकार किया जाना चाहिए, वह यह है।
लोरेटोपरसी

1
मेरी जरूरतों के लिए सरल, सुरुचिपूर्ण और परिपूर्ण।
रिचआर

उत्तम। और क्षेत्र विनिर्देशक को फ़ील्ड विनिर्देशक की सूची के साथ बदलकर उपनिर्देशिकाओं की गणना करने के लिए बढ़ाया जा सकता है। जैसे,:find . -type f | cut -d/ -f2,3 | sort | uniq -c
अल्गल

15

आप सभी फ़ाइलों को खोजने की व्यवस्था कर सकते हैं, फ़ाइल नामों को हटा सकते हैं, जिससे आपको प्रत्येक फ़ाइल के लिए सिर्फ निर्देशिका नाम वाली एक पंक्ति छोड़नी होगी, और फिर प्रत्येक निर्देशिका के प्रकट होने की संख्या की गणना करें:

find . -type f |
sed 's%/[^/]*$%%' |
sort |
uniq -c

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


यदि आप वर्तमान निर्देशिका के प्रत्येक उप-निर्देशिका में फ़ाइलों की गणना में रुचि रखते हैं, किसी भी उप-निर्देशिका में किसी भी फाइल को तत्काल उप-निर्देशिका में फाइलों के साथ गिनना चाहते हैं, तो मैं sedकेवल प्रिंट करने के लिए आदेश को अनुकूलित करूंगा। शीर्ष-स्तरीय निर्देशिका:

find . -type f |
sed -e 's%^\(\./[^/]*/\).*$%\1%' -e 's%^\.\/[^/]*$%./%' |
sort |
uniq -c

पहला पैटर्न नाम, डॉट, स्लैश, अगले स्लैश और स्लैश तक के नाम को शुरू करता है और लाइन को पहले भाग से बदल देता है, इसलिए:

./dir1/dir2/file1

द्वारा प्रतिस्थापित किया जाता है

./dir1/

दूसरा फाइलों को सीधे वर्तमान निर्देशिका में कैप्चर करता है; उनके पास अंत में एक स्लैश नहीं है, और उन द्वारा प्रतिस्थापित किया जाता है ./। सॉर्ट और काउंट तब केवल नामों की संख्या पर काम करता है।


1
यह उन निर्देशिका नामों को आउटपुट नहीं करता है जिनमें कोई फ़ाइल नहीं है। निश्चित नहीं है कि यह आवश्यक है।
ऑस्टिन फिलिप्स

सच है, यह नहीं है। 'तीस विशेष रूप से इसे ठीक करने के लिए तुच्छ नहीं है, क्योंकि खाली निर्देशिका नामों की भी आउटपुट में प्रदर्शित होने की गारंटी नहीं है find। कुछ हो सकता है: यदि कोई फ़ाइल है dir1/dir2/dir3/file1, लेकिन dir1/dir2इसमें केवल उप-निर्देशिकाएं (कोई सादा फ़ाइलें नहीं) हैं, तो आप इसकी उपस्थिति का अनुमान लगा सकते हैं। लेकिन अगर dir1/dir4कोई फाइल नहीं है, तो यह नाम केवल प्रकट नहीं होता है।
जोनाथन लेफ़लर

बहुत उपयोगी जवाब अगर आप बस वर्तमान निर्देशिका के उपनिर्देशिका देखना चाहते हैं।
19ix में xixixao

बस आपको धन्यवाद कहने के लिए रुक गया। इस पोस्ट किए जाने के 3 साल बाद, मैं प्रति फ़ोल्डर 2nd लेवल फ़ोल्डर्स की गिनती करना चाह रहा था। आपकी पोस्ट मुझे संभावित रूप से छेड़खानी के कई घंटों से बचाती है, ढूंढती है और कौन जानता है
Corvin

13

यहाँ यह करने का एक तरीका है, लेकिन शायद सबसे कुशल नहीं है।

find -type d -print0 | xargs -0 -n1 bash -c 'echo -n "$1:"; ls -1 "$1" | wc -l' --

इस तरह से आउटपुट देता है, निर्देशिका नाम के साथ उस निर्देशिका में प्रविष्टियों की गिनती के बाद। ध्यान दें कि आउटपुट काउंट में डायरेक्टरी प्रविष्टियाँ भी शामिल होंगी, जो आप नहीं चाहते।

./c/fa/l:0
./a:4
./a/c:0
./a/a:1
./a/a/b:0

यह बहुत 3 आदेश (चलाने के लिए महंगा लगता है bash, ls, wcप्रत्येक निर्देशिका द्वारा पाया के लिए) find
जोनाथन लेफ्लर

@JonathanLeffler सहमत है, इसलिए मेरे जवाब की पहली पंक्ति है। आपका समाधान बेहतर है।
ऑस्टिन फिलिप्स

शांत यह है कि मैं क्या देख रहा हूँ मैं पूछ सकता हूँ कि आखिर क्या है - ''?
एक बार

1
@once - बैश कमांड के अंतर्गत आता है जिसे xargs द्वारा देखा जाएगा। से man bash, A -- signals the end of options and disables further option processing। इस स्थिति में यह बैश के लिए तर्क प्रसंस्करण का हिस्सा बनने से मिली एक गुम फाइल को रोक देगा।
ऑस्टिन फिलिप्स

8

हर किसी के समाधान में एक खामी या कोई अन्य है।

find -type d -readable -exec sh -c 'printf "%s " "$1"; ls -1UA "$1" | wc -l' sh {} ';'

स्पष्टीकरण:

  • -type d: हम निर्देशिकाओं में रुचि रखते हैं।
  • -readable: हम केवल उन्हें चाहते हैं यदि उनमें फाइलों को सूचीबद्ध करना संभव है। ध्यान दें कि findयह तब भी एक त्रुटि का उत्सर्जन करेगा जब यह उनमें और अधिक निर्देशिकाओं को खोजने का प्रयास करता है, लेकिन यह -execउनके लिए कॉल करने से रोकता है।
  • -exec sh -c BLAH sh {} ';': प्रत्येक निर्देशिका के लिए, इस स्क्रिप्ट के टुकड़े को रन- $0सेट shऔर $1फ़ाइल नाम पर सेट करें।
  • printf "%s " "$1": पोर्ट्रेट रूप से और न्यूनतम रूप से निर्देशिका नाम प्रिंट करें, उसके बाद केवल एक स्थान है, न कि एक नई रेखा।
  • ls -1UA: सूची फ़ाइलें, प्रति पंक्ति एक, निर्देशिका के क्रम में (पाइप रोकने से बचने के लिए), को छोड़कर केवल विशेष निर्देशिका .और..
  • wc -l: रेखाएँ गिनें

1
फ़ाइल को दिखाने के लिए संशोधन पहले लाइन पर, और उनके द्वारा क्रमबद्ध करने के लिए गिना जाता है:find -type d -readable -exec sh -c 'ls -1UA "$1" | wc -l | tr -d "\n" ; printf "\t%s\n" "$1" ' sh {} ';' | sort -n
इवगेनी

यह कई बार शेल निष्पादित करता है, फिर यह धीमा है और संसाधनों का अत्यधिक उपयोग करता है।
ज़नीक

6

सेबस्टियन के उत्तर का थोड़ा संशोधित संस्करण, findइसके बजाय du(फ़ाइल-आकार-संबंधित ओवरहेड को बाहर निकालने के लिए जिसे duप्रदर्शन करना है और जिसका कभी उपयोग नहीं किया गया है):

 find ./ -mindepth 2 -type f | cut -d/ -f2 | sort | uniq -c | sort -nr

-mindepth 2वर्तमान निर्देशिका में फ़ाइलों को बाहर करने के लिए पैरामीटर का उपयोग किया जाता है। यदि आप इसे हटाते हैं, तो आपको निम्न की तरह लाइनों का एक गुच्छा दिखाई देगा:

  234 dir1
  123 dir2
    1 file1
    1 file2
    1 file3
      ...
    1 fileN

(बहुत पसंद है- duआधारित संस्करण करता है)

यदि आपको वर्तमान निर्देशिका में फ़ाइलों की गणना करने की आवश्यकता है, तो इस वर्धित संस्करण का उपयोग करें:

{ find ./ -mindepth 2 -type f | cut -d/ -f2 | sort && find ./ -maxdepth 1 -type f | cut -d/ -f1; } | uniq -c | sort -nr

आउटपुट निम्न की तरह होगा:

  234 dir1
  123 dir2
   42 .

5

यह भी खोजने के बजाय एलएस पर पाशन के साथ किया जा सकता है

for f in */; do echo "$f -> $(ls $f | wc -l)"; done

स्पष्टीकरण:

for f in */; - सभी निर्देशिकाओं पर लूप

do echo "$f -> - प्रत्येक निर्देशिका नाम का प्रिंट आउट लें

$(ls $f | wc -l) - इस निर्देशिका के लिए कॉल एल एस और लाइनों की गणना


1
यह ठीक से काम नहीं करता है अगर निर्देशिका नाम में व्हाट्सएप हो।
ज़ाइलोल

कोशिश करेंfor f ./* ; do echo $f $(ls "$f" | wc -l); done
4ndt3s

3

यह निर्देशिका का नाम निर्देशिका में फ़ाइलों की संख्या के बाद वापस आ जाना चाहिए।

findfiles() {
    echo "$1" $(find "$1" -maxdepth 1 -type f | wc -l)
}

export -f findfiles

find ./ -type d -exec bash -c 'findfiles "$0"' {} \;

उदाहरण आउटपुट:

./ 6
./foo 1
./foo/bar 2
./foo/bar/bazzz 0
./foo/bar/baz 4
./src 4

export -fआवश्यकता है क्योंकि -execके तर्क findको स्पष्ट रूप से बैश आह्वान जब तक आप एक पार्टी फ़ंक्शन को निष्पादित करने की अनुमति नहीं है, और आप समारोह स्पष्ट रूप से नए खोल करने के लिए वर्तमान क्षेत्र में परिभाषित किया गया निर्यात करने के लिए की जरूरत है।


यह बहुत जटिल लगता है। यह मुझे ऐसा भी लग रहा है जैसे यह एक डायरेक्टरी पदानुक्रम के लिए संचयी गणना देता है जैसे ./dir1/dir2/dir3(फाइलों को dir1और उसके सब-इंडीकेट्रीज़ को एक साथ गिनना, बजाय dir1/dir2/dir3उन फाइलों को अलग-अलग करने की बजाय उन dir1/dir2दोनों से अलग-अलग और उन दोनों से अलग-अलग /dir1)।
जोनाथन लेफ्लर

मैं समझ गया कि लेखक यही चाहता था। यदि ऐसा नहीं है, तो मैं मानता हूं कि उत्तर प्रश्न के लिए प्रासंगिक नहीं है।
Tuxdude

1
@JonathanLeffler - ठीक है, प्रश्न को एक बार फिर से पढ़ते हुए, मुझे एहसास हुआ कि आप सही हैं - तदनुसार उत्तर को संशोधित किया है।
Tuxdude

2

मैंने @glenn jackman के उत्तर और @ pcarvalho के उत्तर को मिला दिया (टिप्पणी सूची में, pcarvalho के उत्तर के साथ कुछ गड़बड़ है क्योंकि चरित्र ' ` ' (बैकटिक) का अतिरिक्त स्टाइल कंट्रोल फ़ंक्शन )।

मेरी स्क्रिप्ट पथ को अनुगामी के रूप में स्वीकार कर सकती है और निर्देशिका सूची को क्रमबद्ध कर सकती हैls -l , साथ ही यह "फ़ाइल नाम में स्थान" की समस्या को भी संभाल सकती है

#!/bin/bash
OLD_IFS="$IFS"
IFS=$'\n'
for dir in $(find $1 -maxdepth 1 -type d | sort); 
do
    files=("$dir"/*)
    printf "%5d,%s\n" "${#files[@]}" "$dir"
done
FS="$OLD_IFS"

स्टैकओवरफ़्लो में मेरा पहला उत्तर, और मुझे आशा है कि यह किसी को मदद कर सकता है ^ _ ^


1

खोजो। -Type f -printf '% h \ n' | सॉर्ट | uniq -c

उदाहरण के लिए देता है:

  5 .
  4 ./aln
  5 ./aln/iq
  4 ./bs
  4 ./ft
  6 ./hot

0

मैंने यहां कुछ अन्य लोगों के साथ प्रयास किया लेकिन फाइल गिनती में शामिल सबफ़ोल्डर्स के साथ समाप्त हो गया जब मुझे केवल फाइलें चाहिए थीं। यह ./folder/path<tab>nnnवर्तमान फ़ोल्डर में प्रत्येक सबफ़ोल्डर के लिए, सबफ़ोल्डर्स सहित फ़ाइलों की संख्या के साथ प्रिंट करता है ।

for d in `find . -type d -print` 
do 
  echo -e "$d\t$(find $d -maxdepth 1 -type f -print | wc -l)"
done

0

किसी दिए गए प्रकार की फ़ाइलों को पुन: प्राप्त करने का आसान तरीका। इस स्थिति में, वर्तमान निर्देशिका में सभी फ़ोल्डरों के लिए .jpg फाइलें:

find . -name *.jpg -print | wc -l


0

एक सुपर फास्ट चमत्कार कमांड, जो एक निर्देशिका में छवियों की संख्या की गणना करने और छवि एक्सटेंशन द्वारा आउटपुट को व्यवस्थित करने के लिए फ़ाइलों को पुन: खोजता है:

find . -type f | sed -e 's/.*\.//' | sort | uniq -c | sort -n | grep -Ei '(tiff|bmp|jpeg|jpg|png|gif)$'

क्रेडिट: https://unix.stackexchange.com/a/386135/354980


0

यह निर्देशिका संरचनाओं के माध्यम से ब्राउज़ करने और गहराई से परिणाम प्रदान करने का एक और तरीका हो सकता है।

find . -type d  | awk '{print "echo -n \""$0"  \";ls -l "$0" | grep -v total | wc -l" }' | sh 

0

मैंने node_modulesविश्लेषण के अंदर सभी निर्देशिकाओं को बाहर करने के लिए स्क्रिप्ट को संपादित किया।

यह जांचने के लिए इस्तेमाल किया जा सकता है कि क्या फाइल की प्रोजेक्ट संख्या अधिकतम संख्या से अधिक है जिसे फाइल वॉचर संभाल सकता है।

find . -type d ! -path "*node_modules*" -print0 | while read -d '' -r dir; do
    files=("$dir"/*)
    printf "%5d files in directory %s\n" "${#files[@]}" "$dir"
done

आपके सिस्टम द्वारा देखी जा सकने वाली अधिकतम फ़ाइलों की जाँच करने के लिए:

cat /proc/sys/fs/inotify/max_user_watches

node_modules फ़ोल्डर को आपके आईडीई / संपादक को धीमी प्रणालियों में पथ से जोड़ा जाना चाहिए, और अन्य फ़ाइलों की गणना आदर्श रूप से अधिकतम से अधिक नहीं होनी चाहिए (जिसे हालांकि बदला जा सकता है)।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.