Jak znaleźć pliki i zsumować ich rozmiary?

12

Chciałbym znaleźć serię plików (na podstawie wyrażenia wieloznacznego) i całkowite użycie ich dysku.

Coś takiego:

$ find . -name 'flibble*' -ctime +90 -exec du -sh {} \;

2.1G    ./flibble_116.log
2.1G    ./flibble_83.log
2.1G    ./flibble_211040_157.log
2.1G    ./flibble3747_51.log

Ta praca. Ale to nie daje rezultatu, którego szukam. Zawiera listę miejsca używanego przez każdy plik, podobnie jak finditeracja przez nie.

To, czego chcę, to suma duwszystkich znalezionych plików.

Paweł
źródło

Odpowiedzi:

12

Rozwiązanie

Podając opcję -c(lub --total) du(1), możesz poinstruować ją, aby wygenerowała wielką sumę. Jeśli implementacja du(1)obsługuje jedną z tych opcji, można osiągnąć pożądany efekt za pomocą następującego polecenia:

$ find . -name 'flibble*' -ctime +90 -exec du -shc {} +

EDYCJA: Pamiętaj, że jeśli liczba plików przekracza maksymalną liczbę parametrów dozwoloną przez system, findmoże nadal być wykonywana commandwiele razy. Niektóre implementacje du(1)obsługują również odczytywanie nazw plików z pliku, który nie cierpi z powodu wspomnianego ograniczenia:

$ find -name 'flibble*' -ctime +90 -print0 > filenames
$ du -shc --files0-from=filenames

Wyjaśnienie

Różnica między semantyką -exec command {} \;i -exec command {} +jest następująca:

  • command {} \;wykonuje się commandraz dla każdego wyniku find. Ścieżka do wyniku jest przekazywana zamiast {}.

    $ touch 1 2 3
    $ find  1 2 3 -maxdepth 0 -exec echo {} \;
    1
    2
    3
  • command {} +wykonuje się command, gdy wszystkie wyniki zostaną pobrane. Ścieżki wyników są przekazywane zamiast {}.

    $ touch 1 2 3
    $ find  1 2 3 -maxdepth 0 -exec echo {} +
    1 2 3

-print0Opcja powoduje find(1)wydrukowanie znalezione nazwy plików na standardowe wyjście oddzielone znakiem NULL, a --files0-fromopcja spowodowane du(1)czytać nazw oddzielonych zerowe. W przeciwieństwie do nowego znaku linii znak null może nie pojawić się w nazwie pliku, więc wynik jest jednoznaczny.

Aby dowiedzieć się więcej o opcjach du(1)i find(1), należy zapoznać się z odpowiednimi stronami:

$ man du
$ man find
Witiko
źródło
2
Możesz mieć wiele podsumowań, jeśli liczba plików jest ważna (1K +) z powodu ograniczenia liczby argumentów wiersza poleceń.
ychaouche
Mogę potwierdzić @ychaouche, problem wystąpił podczas próby oceny rozmiaru ponad 30 000 plików.
Adrien H
Jeśli to problem, niektóre implementacje du(1)również wspierać przeczytaniu nazwy plików z pliku: find 1 2 3 -maxdepth 0 -print0 > filenames; du -shc --files0-from=filenames.
Witiko
4

Spróbuj tego:

du -c `find . -name 'flibble*' -ctime +90` | tail -1

Oryginalne polecenie podaje jeden argument, a następnie wykonuje go, aż przejdzie przez wszystkie argumenty. W ten sposób po prostu podajesz wszystkie argumenty naraz, następnie odcinasz osobne rozmiary i pozostawiasz tylko sumę. Jeśli chcesz, możesz usunąć rurkę i ogon, aby pokazać rozmiar każdego pliku.

Andre S.
źródło
To nie da poprawnych wyników dla ścieżek zawierających spacje. Właściwy sposób to zrobić, używając -exec du -c {} +opcji find, która przekaże nazwy ścieżek niezmienionym du.
Witiko,
4

Możesz spróbować:

find . -name 'flibble*' -ctime +90 -exec du -ch {} + | grep total
skush
źródło
2

Musiałbym findsobie wydrukować rozmiar i użyć innego narzędzia do obliczenia całkowitej:

find . -name 'flibble*' -ctime +90 -printf "%s\n" |
perl -lnE '$sum += $_} END {say $sum'

Jeśli chcesz również zobaczyć nazwy plików:

find . -name 'flibble*' -ctime +90 -printf "%s\t%p\n" |
perl -apE '$sum += $F[0]} END {say $sum'
Glenn Jackman
źródło
1

Jedna linijka, która powinna działać, aby uzyskać łączną liczbę gigabajtów w większości systemów:

echo "$(( ($(find . -name 'flibble*' -ctime +90 -type f -printf '%k+' )0)/1024/1024 )) GB"
Robert Boyd
źródło