Rozmiar wszystkich plików określonego rozszerzenia w drzewie katalogów

17

Chcę znać rozmiar pliku z rozszerzeniem .o (plik obiektowy) w moim folderze domowym.

Mogę znaleźć wszystkie pliki obiektów za pomocą

find . -name '*.o'

Jak mogę teraz obliczyć całkowity rozmiar tych plików?

Alhelal
źródło

Odpowiedzi:

24

Szukasz potoków ( |). Są sposobem łączenia wielu poleceń i przekazywania danych wyjściowych jednego polecenia jako danych wejściowych do drugiego. W takim przypadku chcesz przekazać wszystkie nazwy plików, które znajdziesz jako dane wejściowe du(które obliczają rozmiar). Ponieważ jednak duoczekuje , że nazwy plików, a wyniki findsą tylko listą tekstu (tak, tekst składa się z nazw plików, ale dunie wie, że wszystko, co widzi, to tekst), musisz użyć czegoś takiego, xargsktóry weźmie każdy wiersz tekstu, potraktuj go jak nazwę pliku i przekaż go do du. Łącząc to wszystko, otrzymujemy:

find . -name "*.o" | xargs du -sch
  • zawsze powinieneś cytować wzory, które podajesz find(tak jak ja powyżej "*.o":). Jeśli nie, powłoka rozwinie *.onazwy wszystkich pasujących plików w bieżącym katalogu. W tym przypadku działało tylko dlatego, że nie masz pasujących plików.

  • Te -schflagi dla dudokumentowane są w man du:

    -c, --total
          produce a grand total
    -h, --human-readable
          print sizes in human readable format (e.g., 1K 234M 2G)
    -s, --summarize
          display only a total for each argument
    

Należy jednak pamiętać, że to się nie powiedzie w przypadku nazw plików zawierających białe znaki. Prawie na pewno nie będzie to problemem dla plików obiektowych, ale w przyszłości, jeśli będziesz musiał również zajmować się spacjami, użyj:

find . -name "*.o" -print0 | xargs -0 du -sch

Te -print0marki findwydrukować NULL rozdzielone linie i -0marki xargspodjęcia takich linii jak wejścia.

Alternatywnie możesz findwydrukować same rozmiary, a następnie zsumować je:

find . -name "*.o" -printf '%s\n' | awk '{c+=$1}END{print c}'

Obejdzie to również problem wspomniany przez @Serg w komentarzach, w których jest zbyt wiele argumentów, a polecenie jest podzielone na osobne polecenia.


Jeśli używasz bash(prawdopodobnie używasz), istnieje prostszy sposób:

shopt -s globstar 
du -sch **/*.o

Te shopt globstarmarki dowodzenia **pasują do wszystkich plików i podkatalogów lub więcej. Po włączeniu **/*.odopasuje wszystkie pliki (i katalogi), których nazwa kończy się na .o, więc możemy przekazać to bezpośrednio do du.

Zauważ, że w przeciwieństwie do tego findpodejścia, nie będzie to pasowało do ukrytych plików (tych, których nazwa zaczyna się na a .). Aby je również dopasować, wykonaj:

shopt -s dotglob globstar
du -sch **/*.o
terdon
źródło
Jest trochę problemu z pierwszym. Istnieje coś takiego jak MAXARGS. Będzie więc wiele iteracji dui powstanie wiele totallinii. Oto przykład: paste.ubuntu.com/23092752
Sergiy Kolodyazhnyy
@Erg prawda. Dodałem kolejną opcję, która tego unika.
terdon
Twój pierwszy shopt globstarprzykład pomija -s; Musiałem użyć shopt -s globstarpodobnego do twojego drugiego przykładu.
CrazyPyro
@CrazyPyro d'oh! Przepraszam, to była literówka. Dzięki za zwrócenie na to uwagi. shopt OPTIONbez -slub lub -u(lub innej opcji, zobacz help shopt) po prostu drukuje bieżącą wartość OPCJI. Musisz shopt -s OPTIONje włączyć i shopt -u OPTIONwyłączyć.
terdon
8

Użyj -exec flagi, aby uruchomić dupolecenie z ;(co oznacza dla każdego pliku)

find . -name "*.o" -exec du -b {} \; | awk '{total+=$1}END{print total}' 

Przykładowe dane wyjściowe:

$ find . -name "*.txt"  -exec du -b {} \; | awk '{total+=$1}END{print total,"bytes" }'                                     
find: ‘./.cache/gvfs-burn’: Permission denied
find: ‘./.cache/unity’: Permission denied
852690242 bytes

findjest rekurencyjny - co oznacza, że ​​przechodzi przez wszystkie podkatalogi. Jeśli chcesz tylko uzyskać wszystkie *.opliki w bieżącym katalogu, po prostu zrób

du -b -c *.o
Sergiy Kolodyazhnyy
źródło
0

z perlem:

perl -le 'map { $sum += -s } @ARGV; print $sum' -- *.pdf

Rozmiar wszystkich nie ukrytych plików PDF w bieżącym katalogu.

craken
źródło
1
OK, ale OP szuka .oplików i mogą znajdować się w podkatalogach. Możesz także dodać }{wcześniej, print $sumaby uniknąć drukowania sumy dla każdej iteracji. Chcemy tylko ostatniego.
terdon