Como encontro arquivos e totalizo seus tamanhos?

12

Gostaria de encontrar uma série de arquivos (com base em uma expressão curinga) e totalizar o uso do disco.

Algo assim:

$ 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

Este trabalho. Mas não produz o resultado que estou procurando. Ele lista o espaço usado por cada arquivo, conforme finditerativo através deles.

O que eu quero é o total dupara todos os arquivos encontrados.

Paulo
fonte

Respostas:

12

Solução

Ao fornecer a opção -c(ou --total) para du(1), você pode instruí-la a produzir um total geral. Se sua implementação de du(1)suportar alguma dessas opções, você poderá obter o efeito desejado usando o seguinte comando:

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

EDIT: Observe que, se o número de arquivos exceder o número máximo de parâmetros permitido pelo seu sistema, findainda poderá ser executado commandvárias vezes. Algumas implementações du(1)também suportam a leitura dos nomes de arquivos de um arquivo, que não sofre a limitação mencionada:

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

Explicação

A diferença entre a semântica de -exec command {} \;e -exec command {} +é a seguinte:

  • command {} \;executa commanduma vez para cada resultado de find. O nome do caminho do resultado é passado em vez de {}.

    $ touch 1 2 3
    $ find  1 2 3 -maxdepth 0 -exec echo {} \;
    1
    2
    3
    
  • command {} +executa command, quando todos os resultados foram recuperados. Os nomes dos caminhos dos resultados são passados ​​em vez de {}.

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

A -print0opção faz find(1)com que os nomes de arquivos encontrados sejam impressos na saída padrão separada pelo caractere nulo, e a --files0-fromopção causou du(1)a leitura dos nomes de arquivos separados por nulo. Diferentemente do novo caractere de linha, o caractere nulo pode não aparecer em um nome de arquivo, portanto, a saída é inequívoca.

Para saber mais sobre as opções de du(1)e find(1), você deve consultar as respectivas páginas de manual:

$ man du
$ man find
Witiko
fonte
2
Você pode acabar com vários totais se o número de arquivos for importante (1K +) devido à limitação do número de argumentos da linha de comando.
ychaouche
Posso confirmar @ychaouche, peguei o problema ao tentar avaliar o tamanho de mais de 30k arquivos.
Adrien H
Se isso é um problema, algumas implementações de du(1)também apoiar lendo os nomes de arquivos a partir de um arquivo: find 1 2 3 -maxdepth 0 -print0 > filenames; du -shc --files0-from=filenames.
Witiko 16/04/19
4

Tente o seguinte:

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

O comando original está fornecendo um argumento e, em seguida, executando-o, até que ele passe por todos os argumentos. Dessa forma, você simplesmente está apresentando todos os argumentos de uma só vez, cortando os tamanhos separados e deixando apenas o total. Você pode remover o tubo e a cauda para mostrar o tamanho de cada arquivo, se desejar.

Andre S.
fonte
Isso não produzirá resultados corretos com nomes de caminho que contêm espaços. A maneira correta de fazer isso é usar a -exec du -c {} +opção de find, que passará os nomes de caminho inalterados para du.
Witiko
4

Você pode tentar isso:

find . -name 'flibble*' -ctime +90 -exec du -ch {} + | grep total
skush
fonte
2

Eu mesmo teria que findimprimir o tamanho e usar outra ferramenta para calcular o total:

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

Se você também quiser ver os nomes dos arquivos:

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

Um liner que deve funcionar para obter um total de Gigabyte na maioria dos sistemas:

echo "$(( ($(find . -name 'flibble*' -ctime +90 -type f -printf '%k+' )0)/1024/1024 )) GB"
Robert Boyd
fonte