Załóżmy, że istnieje katalog przechowywania obrazów, powiedzmy, ./photos/john_doe
w którym znajduje się wiele podkatalogów, w których znajduje się wiele określonych plików (powiedzmy *.jpg
). Jak obliczyć rozmiar tych plików poniżej john_doe
gałęzi?
Próbowałem du -hs ./photos/john_doe/*/*.jpg
, ale pokazuje tylko pojedyncze pliki. Ponadto śledzi to tylko pierwszy poziom zagnieżdżenia john_doe
katalogu, podobnie jak john_doe/june/
, ale przeskakuje john_doe/june/outrageous/
.
Jak więc mógłbym przejść całą gałąź, sumując rozmiar niektórych plików?
files
directory
directory-structure
size
mbaitoff
źródło
źródło
LC_ALL=POSIX
jako prefiks, aby zawsze grep dla sumy w ten sposób:LC_ALL=POSIX find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$
-name
, zmień grep na, wgrep -P "\ttotal$"
przeciwnym razie przechwyci on również wszystkie pliki kończące się na „total”.bc
, więc oto bardziej przenośne rozwiązanie:find -name '*.jpg' -type f -exec du -bc {} + | grep total$ | cut -f1 | awk '{ total += $1 }; END { print total }'
daje mi całkowite wykorzystanie moich
.jpg
plików w tym katalogu.Aby poradzić sobie z wieloma katalogami, prawdopodobnie musiałbyś
find
jakoś to połączyć .Przydatne mogą być przykłady poleceń du (obejmuje to również
find
)źródło
-R
opcji na man7.org/linux/man-pages/man1/du.1.html . I nie sądzę, aby opcja rekurencyjna pomogła w tym przypadku, ponieważ powłoka wykonuje globalną ekspansję przed przekazaniem argumentówdu
.Przede wszystkim potrzebujesz dwóch rzeczy:
-c
opcjadu
, aby poinformować go do produkcji ogólnej sumy;**
( instrukcje aktywacją ) lubfind
( przykład ) lub przechodzić podkatalogów.źródło
find
może zwrócić błędne wyniki.du -ch -- ./{dir1,dir2}/*.jpg
lubdu -ch -- ./{prefix1*,prefix2*}.jpg
Argument list too long
błąd podczas przetwarzania około 300 000 plików tekstowych.getconf ARG_MAX
. Jeśli masz więcej, musisz przetworzyć pliki pojedynczo lub partiami za pomocą pętli for.Ostateczna odpowiedź to:
i jeszcze szybsza wersja, nie ograniczona przez pamięć RAM, ale wymaga GNU AWK z obsługą bignum:
Ta wersja ma następujące funkcje:
find
określania plików, których szukaszfind
robi proste dopasowanie wieloznaczny nazw plików5.5K
,176.7M
, ...)| numfmt --to=si
źródło
Odpowiedzi podane do tej pory nie biorą pod uwagę, że lista plików przekazywana z find na du może być tak długa, że find automatycznie dzieli listę na części, co powoduje wielokrotne występowanie
total
.Możesz albo
grep total
(locale!) I podsumować ręcznie, albo użyć innego polecenia. AFAIK są tylko dwa sposoby na uzyskanie całkowitej sumy (w kilobajtach) wszystkich plików znalezionych przez find:find . -type f -iname '*.jpg' -print0 | xargs -r0 du -a| awk '{sum+=$1} END {print sum}'
Objaśnienie
find . -type f -iname '*.jpg' -print0
: Znajdź wszystkie pliki z rozszerzeniem jpg bez względu na wielkość liter (tj. * .Jpg, * .JPG, * .Jpg ...) i wyślij je (zakończone zerem).xargs -r0 du -a
: -r: Xargs wywołałby polecenie nawet bez podania argumentów, co zapobiega -r. -0 oznacza łańcuchy zakończone znakiem null (nie zakończone znakiem nowej linii).awk '{sum+=$1} END {print sum}'
: Zsumuj rozmiary plików wyjściowych za pomocą poprzedniego poleceniaDla porównania, byłby inny sposób
find . -type f -iname '*.jpg' -print0 | du -c --files0-from=-
źródło
du --file0-from
trwało to dłużej, ponieważ najpierw go uruchomiłeś (efekt buforowania).xargs
kilkadu -a
, więc mogą występować rozbieżności, jeśli istnieją twarde linki.Jeśli lista plików jest zbyt duża, aby nie można jej było przekazać do pojedynczego wywołania
du -c
, w systemie GNU możesz wykonać:(rozmiar wyrażony liczbą 512 bajtów bloków). Tak
du
jakby próbował policzyć twarde linki tylko raz. Jeśli nie zależy ci na linkach twardych, możesz uprościć to:Jeśli chcesz rozmiar zamiast użycia dysku, wymień
%b
się%s
. Rozmiar zostanie wówczas wyrażony w bajtach.źródło
-bash: bc: command not found
Centos - Linux 2.6.32-431.el6.x86_64bc
to nie opcjonalne polecenie POSIX.Wspomniane rozwiązania są nieefektywne (wykonanie jest drogie) i wymagają dodatkowej pracy ręcznej, aby zsumować, jeśli lista plików jest długa lub nie działają w systemie Mac OS X. Poniższe rozwiązanie jest bardzo szybkie, powinno działać na każdym systemie i daje całkowitą odpowiedź w GB (usuń a / 1024, jeśli chcesz zobaczyć sumę w MB):
find . -iname "*.jpg" -ls |perl -lane '$t += $F[6]; print $t/1024/1024/1024 . " GB"'
źródło
-iname
też nie-ls
są standardowe / przenośne, więc też nie będzie działać na żadnym systemie . Nie będzie również działać poprawnie, jeśli istnieją nazwy plików lub cele dowiązań symbolicznych zawierające znaki nowej linii.Ulepszając świetną odpowiedź SHW, aby działała z dowolnymi lokalizacjami, jak Zbyszek już zauważył w swoim komentarzu:
źródło
du oczywiście przegląda hierarchię katalogów, a awk może przeprowadzić filtrowanie, więc coś takiego może być wystarczające:
Działa to bez GNU.
źródło
stat
wezwanie do plików, które nie odpowiadają wyszukanemu wzorowi.