एक निर्देशिका शाखा के भीतर कुछ फ़ाइलों के कुल आकार का पता लगाएं


140

मान लें कि एक छवि संग्रहण निर्देशिका है, कहते हैं, ./photos/john_doeजिसके भीतर कई उपनिर्देशिकाएं हैं, जहां कई निश्चित फाइलें रहती हैं (कहती हैं *.jpg)। मैं john_doeशाखा के नीचे उन फ़ाइलों के सारांश आकार की गणना कैसे कर सकता हूं ?

मैंने कोशिश की du -hs ./photos/john_doe/*/*.jpg, लेकिन यह केवल व्यक्तिगत फ़ाइलों को दिखाता है। इसके अलावा, यह john_doeनिर्देशिका के पहले घोंसले के स्तर को पसंद करता है john_doe/june/, जैसे , लेकिन स्किप करता है john_doe/june/outrageous/

तो, मैं पूरी शाखा को कैसे पार कर सकता हूं, कुछ फाइलों के आकार को संक्षेप में बता सकता हूं?

जवाबों:


183
find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$

यदि एक से अधिक आह्वान की duआवश्यकता है क्योंकि फ़ाइल सूची बहुत लंबी है, तो कई योगों की सूचना दी जाएगी और उन्हें समन करने की आवश्यकता होगी।


7
find -iname 'file *' -exec du -cb {} + | grep कुल $ | कट -फ १ | पेस्ट -sd + - | bc # संक्षेप बाइट का आकार
मीकल #izmazia

3
यदि आपका सिस्टम अन्य भाषा के तहत काम करता है तो आपको कुल $ $ शब्द को दूसरे शब्द जैसे कि पोलिश में $ बदलने की जरूरत है।
Zbyszek

1
आप LC_ALL=POSIXइस तरह से कुल के लिए हमेशा उपसर्ग के रूप में जोड़ सकते हैं :LC_ALL=POSIX find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$
स्वेन

2
यदि आप उपयोग नहीं कर रहे हैं -name, तो grep को बदल दें grep -P "\ttotal$"अन्यथा यह "कुल" के साथ समाप्त होने वाली सभी फ़ाइलों को भी कैप्चर करेगा।
शाम

3
@ MichalČizmazia कुछ गोले (जैसे, विंडोज के लिए Git बैश) नहीं के साथ आते हैं bc, तो यहाँ एक अधिक पोर्टेबल समाधान है:find -name '*.jpg' -type f -exec du -bc {} + | grep total$ | cut -f1 | awk '{ total += $1 }; END { print total }'
thdoan

50
du -ch public_html/images/*.jpg | grep total
20M total

मुझे .jpgइस निर्देशिका में अपनी फ़ाइलों का कुल उपयोग देता है ।

कई निर्देशिकाओं से निपटने के लिए आपको शायद इसे findकिसी भी तरह से जोड़ना होगा ।

आपको डु कमांड के उदाहरण उपयोगी लग सकते हैं (इसमें शामिल भी हैं find)


2
यह अंतर्निहित निर्देशिकाओं को पार नहीं करता है?
म्बिटॉफ

यह स्वीकृत समाधान की तुलना में टाइप करना आसान है, लेकिन यह केवल आधा-सही है, इसमें उपनिर्देशिकाओं में छवियां शामिल नहीं होंगी। यह जानने के लिए अच्छा है कि सभी फाइलें एक निर्देशिका में हैं या नहीं।
gbmhunter

@gbmhunter मुझे लगता है कि यदि आप -R पैरामीटर को जोड़ते हैं, तो आप उपनिर्देशिका भी प्राप्त कर लेंगे क्योंकि यह निर्देशिका ट्री को पुन: खोजता है। मैं वर्तमान में पुष्टि करने के लिए इसे आज़माने के लिए कंप्यूटर पर नहीं हूँ।
लेवोन

1
मुझे man7.org/linux/man-pages/man1/du.1.html-R पर कोई विकल्प दिखाई नहीं देता है । और मुझे नहीं लगता कि एक पुनरावर्ती विकल्प इस मामले में मदद करेगा, क्योंकि शेल तर्कों को पारित करने से पहले ग्लोब विस्तार कर रहा है । du
gbmhunter 21

22

मुख्य रूप से, आपको दो चीजें चाहिए:

  • एक भव्य कुल उत्पादन करने के लिए यह बताने का -cविकल्प du;
  • या तो **( सक्रियण निर्देश ) या find( उदाहरण ) या उपनिर्देशिका को पार करने के लिए।
du -ch -- **/*.jpg | tail -n 1

बहुत अच्छा जवाब। खोज का उपयोग करने की तुलना में सरल (लंबे समय तक * या ** निर्देशिका संरचना से मेल खाता है)
आंद्रे डी मिरांडा

यह फ़ाइलों की बहुत लंबी सूची को भी संभाल सकता है जबकि उपयोग करने से findगलत परिणाम मिल सकते हैं।
एरिक फोनी

बैश ब्रेस विस्तार वाइल्डकार्ड के कई सेटों को मापने के लिए भी अनुमति देता है। du -ch -- ./{dir1,dir2}/*.jpgयाdu -ch -- ./{prefix1*,prefix2*}.jpg
J.Money

@EricFournie हालांकि मुझे Argument list too longलगभग 300k पाठ फ़ाइलों को संसाधित करते समय त्रुटि हुई।
xtluo

एक कमांड के लिए अधिकतम तर्क (इस मामले में, वाइल्डकार्ड विस्तार द्वारा लौटाए गए फ़ाइल नाम) के साथ जांच की जा सकती है getconf ARG_MAX। यदि आपके पास अधिक है, तो आपको एक लूप के साथ एक या एक बैचवाइज़ फ़ाइलों को संसाधित करने की आवश्यकता होगी।
एरिक फोनी

17

अंतिम उत्तर है:

{ find <DIR> -type f -name "*.<EXT>" -printf "%s+"; echo 0; } | bc

और इससे भी तेज संस्करण, रैम द्वारा सीमित नहीं है, लेकिन इसके लिए bignum समर्थन के साथ GNU AWK की आवश्यकता है:

find <DIR> -type f -name "*.<EXT>" -printf "%s\n" | gawk -M '{t+=$1}END{print t}'

इस संस्करण में निम्नलिखित विशेषताएं हैं:

  • findआपके द्वारा ढूंढी जा रही फ़ाइलों को निर्दिष्ट करने की सभी क्षमताएं
  • लाखों फ़ाइलों का समर्थन करता है
    • अन्य उत्तर यहां तर्क सूची की अधिकतम लंबाई तक सीमित हैं
  • एक न्यूनतम पाइप थ्रूपुट के साथ केवल 3 सरल प्रक्रियाएं पैदा करता है
    • कई उत्तर यहाँ C + N प्रक्रियाओं को दर्शाते हैं, जहाँ C कुछ स्थिर है और N फाइलों की संख्या है
  • स्ट्रिंग हेरफेर के साथ परेशान नहीं करता है
    • यह संस्करण किसी भी प्रकार की तैयारी, या पुनर्लेखन नहीं करता है
    • ठीक है, findफ़ाइलनामों का एक साधारण वाइल्डकार्ड मिलान करता है
  • वैकल्पिक रूप से एक मानव पठनीय रूप में योग स्वरूपों (जैसे। 5.5K, 176.7M, ...)
    • उस append करने के लिए | numfmt --to=si

मुझे इस उत्तर की सादगी पसंद है, हालांकि यह केवल मेरे लिए काम करता है जब मैंने उद्घाटन ब्रेस के बाद और समापन ब्रेस से पहले रिक्त स्थान पेश किया। मुझे आश्चर्य है कि अगर यह वास्तव में फ़ाइलों की एक 'infininte' संख्या का समर्थन करेगा :)
andyb

1
@ कैंडी प्रतिक्रिया के लिए धन्यवाद, ब्रेसिज़ के आसपास के रिक्त स्थान वास्तव में BASH में आवश्यक हैं, मैं ZSH का उपयोग कर रहा हूं इसलिए मैंने यह नोटिस नहीं किया। और आपके सिस्टम पर उपलब्ध RAM द्वारा फाइलों की संख्या सीमित है क्योंकि bc की मेमोरी उपयोग धीरे-धीरे संख्या में प्रवाह के रूप में बढ़ता है।
Jan Chren - rindeal

8

अब तक दिए गए उत्तर इस बात पर ध्यान नहीं देते हैं कि फ़ाइल सूची को डू से डू में पारित करने के लिए इतना लंबा हो सकता है कि खोज स्वचालित रूप से सूची को विखंडू में विभाजित कर देती है, जिसके परिणामस्वरूप कई घटनाएं होती हैं total

आप या तो grep total(स्थानीय)! और मैन्युअल रूप से योग कर सकते हैं, या एक अलग कमांड का उपयोग कर सकते हैं। AFAIK खोजने के लिए मिली सभी फाइलों का एक भव्य कुल (किलोबाइट में) प्राप्त करने के केवल दो तरीके हैं:
find . -type f -iname '*.jpg' -print0 | xargs -r0 du -a| awk '{sum+=$1} END {print sum}'

स्पष्टीकरण
find . -type f -iname '*.jpg' -print0: मामले की परवाह किए बिना एक्सटेंशन jpg के साथ सभी फ़ाइलें खोजें (जैसे * .jpg, * .JPG, * .Jpg ...) और उन्हें आउटपुट (शून्य-समाप्त)।
xargs -r0 du -a: -r: Xargs कमांड को कॉल करेगा यहां तक ​​कि कोई तर्क पारित नहीं हुआ, जो -r रोकता है। -0 का अर्थ है, शून्य-समाप्त स्ट्रिंग्स (न्यूलाइन समाप्त नहीं)।
awk '{sum+=$1} END {print sum}': पिछले कमांड द्वारा फाइल साइज आउटपुट को योग करें

और संदर्भ के लिए, दूसरा तरीका होगा
find . -type f -iname '*.jpg' -print0 | du -c --files0-from=-


अतिरिक्त संकेत: मेरे HDD पर 23428 फाइलें (22323 इमेजेज) होने के कारण पहला तरीका 1 सेकंड चलता है जबकि दूसरा 3.8 सेकंड चलता है।
Jan

ध्यान दें कि दोनों एक GNU प्रणाली को मानते हैं। पहले एक फ़ाइल नाम में newline वर्ण नहीं हैं।
स्टीफन चेजलस

मैं शर्त लगा सकता हूं du --file0-fromकि आप इसे पहले ले गए (कैशिंग प्रभाव)।
स्टीफन चेज़लस

के साथ xargs, कई du -aचलाए जा सकते हैं, इसलिए यदि आपके पास हार्ड लिंक हैं तो विसंगतियां हो सकती हैं।
स्टीफन चेज़लस

3

यदि फ़ाइलों की सूची बहुत बड़ी है कि इसे du -cGNU सिस्टम पर एक ही मंगलाचरण के लिए पारित नहीं किया जा सकता है, तो आप यह कर सकते हैं:

find . -iname '*.jpg' -type f -printf '%b\t%D:%i\n' |
  sort -u | cut -f1 | paste -sd+ - | bc

(आकार 512 बाइट ब्लॉक की संख्या में व्यक्त किया गया)। जैसे duयह हार्ड लिंक को केवल एक बार गिनने की कोशिश करता है। यदि आपको हार्डलिंक की परवाह नहीं है, तो आप इसे सरल बना सकते हैं:

(printf 0; find . -iname '*.jpg' -type f -printf +%b) | bc

आप आकार के बजाय डिस्क उपयोग चाहते हैं, की जगह %bके साथ %s। आकार तब बाइट्स में व्यक्त किया जाएगा।


-bash: bc: command not foundसेंटोस - लिनक्स 2.6.32-431.el6.x86_64
yeya

@yeya, लगता है जैसे आपका CentOS परिनियोजन टूट गया है। bcएक गैर-वैकल्पिक POSIX कमांड है।
स्टीफन चेजलस

1

अब तक उल्लिखित समाधान अक्षम हैं (निष्पादन महंगा है) और अतिरिक्त मैनुअल काम की आवश्यकता है यदि फ़ाइल सूची लंबी है या वे मैक ओएस एक्स पर काम नहीं करते हैं। निम्नलिखित समाधान बहुत तेज़ है, किसी भी सिस्टम पर काम करना चाहिए, और GB में कुल उत्तर देता है (यदि आप MB में कुल देखना चाहते हैं तो / 1024 हटा दें): find . -iname "*.jpg" -ls |perl -lane '$t += $F[6]; print $t/1024/1024/1024 . " GB"'


न तो -inameहै और न ही -lsमानक / पोर्टेबल हैं, तो यह नहीं होगा किसी भी सिस्टम पर काम या तो। यह भी ठीक से काम नहीं करेगा अगर वहाँ कोई फ़ाइल नाम या सिमलिंक लक्ष्य होते हैं जिसमें न्यूलाइन वर्ण होते हैं।
स्टीफन चेजलस

यह भी ध्यान दें कि यह फ़ाइल के आकार का योग देता है, न कि उनका डिस्क उपयोग। सीमलिंक के लिए, यह साइमलिंक का आकार देता है, न कि उन फाइलों की ओर, जो वे इंगित करते हैं।
स्टीफन चेज़लस

1

किसी भी स्थान के साथ काम करने के लिए SHW के शानदार जवाब में सुधार करना, जैसे Zbyszek ने पहले ही अपनी टिप्पणी में बताया:

LC_ALL=C find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$

1

डु स्वाभाविक रूप से निर्देशिका पदानुक्रम का पता लगाता है और awk फ़िल्टरिंग का प्रदर्शन कर सकता है ताकि ऐसा कुछ पर्याप्त हो सके:

du -ak | awk 'BEGIN {sum=0} /\.jpg$/ {sum+=$1} END {print sum}'

यह जीएनयू के बिना काम करता है।


1
यह अधिक महंगा है क्योंकि यह statउन फ़ाइलों के लिए कॉल को मजबूर करता है जो खोजे गए पैटर्न के अनुरूप नहीं हैं।
कानून

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