Bir dizin dalı içindeki belirli dosyaların toplam boyutunu bulun


140

Diyelim ki, ./photos/john_doeiçinde birçok dosyanın bulunduğu birden fazla alt dizinin bulunduğu bir resim saklama dizini var *.jpg. john_doeŞubenin altındaki bu dosyaların bir özet boyutunu nasıl hesaplayabilirim ?

Denedim du -hs ./photos/john_doe/*/*.jpg, ama bu sadece bireysel dosyaları gösteriyor. Ayrıca, bu john_doedizinin yalnızca ilk yuva düzeyini izler , beğenir john_doe/june/, atlar john_doe/june/outrageous/.

Öyleyse, belirli bir dosyanın boyutunu toplayarak şubenin tamamını nasıl geçebilirim?

Yanıtlar:


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

duDosya listesi çok uzun olduğu için birden fazla çağrı yapılması gerekiyorsa, birden fazla toplam bildirilir ve toplanması gerekir.


7
bulmak -iname 'dosya *' -exec du -cb {} + | grep toplam $ | cut -f1 | yapıştır -sd + - | bc # toplam bayt büyüklüğü
Michal Čizmazia

3
Sisteminiz başka bir dilde çalışıyorsa, toplam $ 'ı Lehçe'daki razem $ gibi bir sözcüğe değiştirmeniz gerekir.
Zbyszek

1
Her LC_ALL=POSIXzaman bu gibi toplam grep önek olarak ekleyebilirsiniz :LC_ALL=POSIX find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$
Sven

2
Eğer kullanmıyorsanız -name, o zaman grep değiştirmek grep -P "\ttotal$"illâ o "toplam" yanı ile biten tüm dosyaları yakalayacaktır.
thdoan

3
@ MichalČizmazia ile bazı mermiler (örneğin, Windows için Git Bash) birlikte gelmiyor bc, işte daha taşınabilir bir çözüm:find -name '*.jpg' -type f -exec du -bc {} + | grep total$ | cut -f1 | awk '{ total += $1 }; END { print total }'
1717

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

bana .jpgbu dizindeki dosyalarımın toplam kullanımını verir .

Birden fazla dizinle başa çıkmak için muhtemelen bir şekilde bunu birleştirmeniz gerekir find.

Du komutu örneklerini yararlı bulabilirsiniz (ayrıca içerir find)


2
Bu altta yatan dizinleri geçmiyor mu?
mbaitoff

Bu, kabul edilen çözümden yazmak daha kolaydır, ancak yalnızca yarı haklıdır, alt dizinlerde görüntü içermez. Tüm dosyaların bir dizinde olup olmadığını bilmek güzel.
gbmhunter

@gbmhunter -ch parametresine -ch parametresini eklerseniz, dizin ağacını yinelemeli olarak geçtiğinde alt dizinleri de alırsınız. Şu anda onaylamak için denemek için bir bilgisayarda değilim.
Levon

1
Man7.org/linux/man-pages/man1/du.1.html-R adresinde bir seçenek göremiyorum . Özyinelemeli bir seçeneğin bu durumda yardımcı olacağını sanmıyorum çünkü kabuk argümanları iletmeden önce genişleme yapıyor du.
gbmhunter

22

Öncelikle iki şeye ihtiyacınız var:

du -ch -- **/*.jpg | tail -n 1

çok iyi cevap. Bulunmasını kullanmaktan daha basittir (* veya ** dizin yapısına
Andre de Miranda

Ayrıca çok uzun dosya listelerini kullanabilir, bununla birlikte kullanılması findhatalı sonuçlar verebilir.
Eric Fournie 19:16

bash ayraç genişlemesi, birden çok joker karakter kümesinin ölçülmesine olanak tanır. du -ch -- ./{dir1,dir2}/*.jpgya dadu -ch -- ./{prefix1*,prefix2*}.jpg
J.Money

@EricFournie Ancak Argument list too longyaklaşık 300k metin dosyası işlenirken hata oluştu .
xtluo

Bir komut için maksimum argüman sayısı (bu durumda, joker karakter genişletmesi tarafından döndürülen dosya adları) ile kontrol edilebilir getconf ARG_MAX. Daha fazlasınız varsa, dosyaları bir for döngüsü ile birer birer veya toplu olarak işlemeniz gerekir.
Eric Fournie

17

Nihai cevap:

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

ve daha hızlı versiyon, RAM ile sınırlı değildir, ancak bunun için bignum desteği ile GNU AWK gerekir:

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

Bu sürüm aşağıdaki özelliklere sahiptir:

  • findaradığınız dosyaları belirtmek için tüm yetenekler
  • milyonlarca dosyayı destekler
    • Buradaki diğer cevaplar, tartışma listesinin azami uzunluğu ile sınırlıdır.
  • Minimum boru verimi ile sadece 3 basit işlem ortaya çıkarır
    • buradaki birçok cevap C + N işlemlerini doğurur, burada C bazı sabit, N ise dosya sayısıdır
  • string manipülasyon ile uğraşmaz
    • Bu sürüm hiçbir grepping veya regexing yapmaz
    • Peki, findbasit bir joker dosya isimleri eşleştirme yapar
  • isteğe bağlı olarak bir insan tarafından okunabilir formda toplamı biçimlendirir (örn. 5.5K, 176.7M, ...)
    • bunu yapmak için | numfmt --to=si

Bu cevabın basitliğini seviyorum, ancak yalnızca benim için açılış açılışından sonra ve kapanış kümesinden önce boşluklar yerleştirdiğimde işe yaradı. Gerçekten de olsa bir 'infiinte' dosya sayısını destekleyip desteklemediğini merak ediyorum :)
andyb

1
@andyb geri bildirim için teşekkürler, BASH'de parantezlerin etrafındaki boşluklar gerçekten gerekli, ZSH kullanıyorum, bu yüzden farketmedim. Dosya sayıları sisteminizde mevcut RAM ile sınırlıdır, çünkü
bc'nin

8

Şimdiye kadar verilen cevaplar, dosyadan find'den du'ya geçirilen dosya listesinin o kadar uzun olabilir ki, bulma otomatik olarak listeyi otomatik olarak parçalara böler ve bu da çoklu oluşumlara neden olur total.

grep total(Yerel!) Ya da elle toplayabilir veya farklı bir komut kullanabilirsiniz. AFAIK, bulduğu tüm dosyaların genel toplamını (kilobayt cinsinden) almanın yalnızca iki yolu vardır:
find . -type f -iname '*.jpg' -print0 | xargs -r0 du -a| awk '{sum+=$1} END {print sum}'

Açıklama
find . -type f -iname '*.jpg' -print0: Her ne olursa olsun (örneğin, * .jpg, * .JPG, * .Jpg ...) jpg uzantılı tüm dosyaları bulun ve bunları (null) sonlandırın.
xargs -r0 du -a: -r: Xargs komutu argüman olmadan bile çağırır, ki -r önler. -0 boş sonlandırılmış karakter dizileri (yeni satır sonlandırılmamış) anlamına gelir.
awk '{sum+=$1} END {print sum}': Çıktı dosya boyutlarını önceki komutla topla

Ve referans için, diğer yol
find . -type f -iname '*.jpg' -print0 | du -c --files0-from=-


Ek ipucu: 23428 dosyalı (22323 görüntü) HDD'mde ilk yöntem 1 saniye, ikincisi ise 3,8 saniye çalışıyor.
Jan

Her ikisinin de bir GNU sistemi varsaydığını unutmayın. İlki, dosya adlarının yeni satır karakterleri içermediğini varsayar.
Stéphane Chazelas

Bahse girerim du --file0-fromdaha uzun sürdü çünkü ilk sen koştun (önbellekleme etkisi).
Stéphane Chazelas

İle xargs, birkaç du -açalıştırılabilir, bu yüzden sert bağlantılar varsa tutarsızlıklar olabilir.
Stéphane Chazelas

3

Dosyaların listesi du -c, bir GNU sisteminde tek bir çağrıya geçirilemeyecek kadar büyükse , şunları yapabilirsiniz:

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

(512 bayt blok sayısında ifade edilen boyut). duSert bağlantıları sadece bir kez saymaya çalışır gibi . Bağlantıları umursamıyorsanız, şunları basitleştirebilirsiniz:

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

Eğer boyutunu yerine disk kullanımını istiyorsanız, yerini %bile %s. Boyut daha sonra bayt olarak ifade edilir.


-bash: bc: command not foundCentos - Linux 2.6.32-431.el6.x86_64
yeya

@yeya, CentOS dağıtımınız bozuldu gibi geliyor. bcisteğe bağlı olmayan bir POSIX komutu.
Stéphane Chazelas

1

Şimdiye kadar bahsedilen çözümler yetersizdir (yürütme pahalıdır) ve dosya listesi uzunsa veya Mac OS X'te çalışmıyorsa, toplanmaları için ek elle çalışmayı gerektirir. Aşağıdaki çözüm çok hızlıdır, herhangi bir sistemde çalışmalıdır ve toplam cevabı GB cinsinden verir (toplamı MB cinsinden görmek istiyorsanız a / 1024’i kaldırın): find . -iname "*.jpg" -ls |perl -lane '$t += $F[6]; print $t/1024/1024/1024 . " GB"'


Ne standart / -inamene -lstaşınabilir ne de herhangi bir sistemde çalışmaz . Ayrıca, yeni satır karakterleri içeren dosya adları veya sembolik bağlantı hedefleri varsa düzgün çalışmaz.
Stéphane Chazelas,

Ayrıca, disk kullanımlarının değil, dosya boyutlarının toplamını verdiğini unutmayın. İşaret halkaları için, işaret ettikleri dosyaları değil, işaret bağlantılarının boyutunu verir.
Stéphane Chazelas

1

SHB'nin herhangi bir yerel ayarla çalışması için büyük cevabını geliştirmek, Zbyszek'in yorumunda çoktan belirtildiği gibi:

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

1

du doğal olarak dizin hiyerarşisini dolaşır ve awk filtrelemeyi gerçekleştirebilir, böylece böyle bir şey yeterli olabilir:

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

Bu GNU'suz çalışır.


1
Bu daha pahalıdır, çünkü stataranan formata karşılık gelmeyen dosyalar için bir çağrı gerektirir .
Law29

Yalnızca bu çözüm mac'umda çalışıyor.
Matthias M
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.