Předpokládejme, že existuje adresář pro ukládání obrázků, řekněme: ./photos/john_doe
, ve kterém je více podadresářů, kde je umístěno mnoho určitých souborů (řekněme: *.jpg
). Jak mohu vypočítat souhrnnou velikost těchto souborů pod john_doe
větev?
Zkusil jsem du -hs ./photos/john_doe/*/*.jpg
, ale zobrazí se pouze jednotlivé soubory. Také se sleduje pouze první úroveň vnoření john_doe
adresář, například john_doe/june/
, ale přeskočí john_doe/june/outrageous/
.
Jak tedy mohu projít celou větev a shrnout velikost určitých souborů?
find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$
Pokud je vyžadováno více než jedno vyvolání du
, protože seznam souborů je velmi dlouhý, bude hlášeno více součtů a je třeba je sečíst.
du -ch public_html/images/*.jpg | grep total
20M total
dává mi úplné využití mého .jpg
složky v tomto adresáři.
Chcete-li pracovat s více adresáři, pravděpodobně byste to museli zkombinovat s find
nějak.
Možná vám bude příklady příkazů d užitečné (zahrnuje také find
)
Především potřebujete dvě věci:
-c
možnost du
, řekněte jí, aby vytvořil celkový součet;**
( pokyny k aktivaci ) nebo find
( příklad ) nebo k procházení podadresářů.du -ch -- **/*.jpg | tail -n 1
Konečná odpověď zní:
{ find <DIR> -type f -name "*.<EXT>" -printf "%s+"; echo 0; } | bc
a ještě rychlejší verze, neomezená RAM, ale to vyžaduje GNU AWK s podporou bignum):
find <DIR> -type f -name "*.<EXT>" -printf "%s\n" | gawk -M '{t+=$1}END{print t}'
Tato verze má následující funkce:
find
k určení souborů, které hledátefind
provádí jednoduché zástupné porovnávání názvů souborů5.5K
, 176.7M
, ...) | numfmt --to=si
Odpovědi, které byly dosud poskytnuty, neberou v úvahu, že seznam souborů předávaný z find to du může být tak dlouhý, že find automaticky rozdělí seznam do bloků, což má za následek mnohonásobný výskyt total
.
Můžeš buď grep total
(locale!) a sčítejte ručně, nebo použijte jiný příkaz. AFAIK existují pouze dva způsoby, jak získat celkový součet (v kilobajtech) všech souborů nalezených pomocí find:find . -type f -iname '*.jpg' -print0 | xargs -r0 du -a| awk '{sum+=$1} END {print sum}'
Vysvětlenífind . -type f -iname '*.jpg' -print0
: Vyhledejte všechny soubory s příponou jpg bez ohledu na velikost písmen (tj. * .Jpg, * .JPG, * .Jpg ...) a vydejte je (ukončeno nulovou hodnotou).xargs -r0 du -a
: -r: Xargs by příkaz zavolal i bez předání argumentů, což zabrání -r. -0 znamená null zakončené řetězce (nikoli zakončení nového řádku).awk '{sum+=$1} END {print sum}'
: Sčítá výstup velikosti souboru pomocí předchozího příkazu
A pro orientaci by tomu bylo jinakfind . -type f -iname '*.jpg' -print0 | du -c --files0-from=-
Pokud je seznam souborů příliš velký, že jej nelze předat na jediné vyvolání du -c
, v systému GNU) můžete:
find . -iname '*.jpg' -type f -printf '%b\t%D:%i\n' |
sort -u | cut -f1 | paste -sd+ - | bc
(velikost vyjádřená počtem 512 bytových bloků). Stejně jako du
se snaží počítat pevné odkazy pouze jednou. Pokud vám nezáleží na pevných odkazech, můžete je zjednodušit:
(printf 0; find . -iname '*.jpg' -type f -printf +%b) | bc
Pokud chcete místo využití disku velikost, nahraďte %b
s %s
. Velikost bude potom vyjádřena v bajtech.
Dosud zmiňovaná řešení jsou neefektivní (spuštění je drahé) a vyžaduje součet dalších manuálních prací, pokud je seznam souborů dlouhý nebo nefungují v systému Mac OS X. Následující řešení je velmi rychlé, mělo by fungovat na jakémkoli systému a dává celkovou odpověď v GB (odebrat a/1024, pokud chcete vidět součet v MB): find . -iname "*.jpg" -ls |Perl -lane '$t += $F[6]; print $t/1024/1024/1024 . " GB"'
du přirozeně prochází hierarchii adresářů a awk může provádět filtrování, takže něco takového může stačit:
du -ak | awk 'BEGIN {sum=0} /\.jpg$/ {sum+=$1} END {print sum}'
Funguje to bez GNU.
Vylepšuje skvělou odpověď SHW, aby fungovala s jakýmkoli národním prostředím, jak Zbyszek již ve své poznámce zdůraznil:
LC_ALL=C find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$
Další by bylo
ls -al <directory> | awk '{t+=$5}END{print t}}'
Za předpokladu, že hledáte v jednom adresáři. Pokud se chcete podívat na aktuální adresář a pod ním
ls -Ral <directory> | awk '{t+=$5}END{print t}}'
To pro mě fungovalo.
find -type f -iname *.jpg -print0 | du -ch --files0-from=- | grep total$
Jiná alternativa používat stat spíše než du
stat -L -c %s ** | awk '{s+=$1} END {printf "%.0f\n", s}'
Viz Gillesova odpověď na používání **