find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$
Se mais de uma invocação de du
for necessária porque a lista de arquivos é muito longa, vários totais serão informados e precisam ser somados.
Suponha que haja um diretório de armazenamento de imagens, digamos, ./photos/john_doe
, dentro do qual existem vários subdiretórios, onde residem muitos arquivos (digamos, *.jpg
). Como posso calcular um tamanho de resumo desses arquivos abaixo da ramificação john_doe
?
Eu tentei du -hs ./photos/john_doe/*/*.jpg
, mas isso mostra apenas arquivos individuais. Além disso, isso rastreia apenas o primeiro nível de aninhamento do diretório john_doe
, como john_doe/june/
, mas ignora john_doe/june/outrageous/
.
Então, como eu poderia percorrer o ramo inteiro, resumindo o tamanho de certos arquivos?
du -ch public_html/images/*.jpg | grep total
20M total
me dá o uso total dos meus arquivos .jpg
neste diretório.
Para lidar com vários diretórios, você provavelmente terá que combinar isso com find
de alguma forma.
Você pode encontrar du exemplos de comandos úteis (também inclui find
)
A resposta final é:
{ find <DIR> -type f -name "*.<EXT>" -printf "%s+"; echo 0; } | bc
e versão ainda mais rápida, não limitada pela RAM, mas que requer o GNU AWK com suporte a bignum:
find <DIR> -type f -name "*.<EXT>" -printf "%s\n" | gawk -M '{t+=$1}END{print t}'
Esta versão possui os seguintes recursos:
find
para especificar os arquivos que você está procurando find
faz uma correspondência simples de caracteres curinga de nomes de arquivos 5.5K
, 176.7M
, ...)
| numfmt --to=si
As respostas dadas até agora não levam em conta que a lista de arquivos passada de find para du pode ser tão longa que o find automaticamente divide a lista em partes, resultando em várias ocorrências de total
.
Você pode grep total
(localidade!) e somar manualmente ou usar um comando diferente. AFAIK existem apenas duas maneiras de obter um total geral (em kilobytes) de todos os arquivos encontrados por find:
find . -type f -iname '*.jpg' -print0 | xargs -r0 du -a| awk '{sum+=$1} END {print sum}'
Explicação de find . -type f -iname '*.jpg' -print0
: Encontre todos os arquivos com a extensão jpg, independentemente do caso (ou seja, * .jpg, * .JPG, * .Jpg ...) e imprima-os (com terminação nula).
%código%:
-r: Xargs chamaria o comando mesmo sem argumentos passados, o que -r previne. -0 significa sequências terminadas em nulo (não terminadas em nova linha).
xargs -r0 du -a
: Soma os tamanhos dos arquivos gerados pelo comando anterior
E para referência, o outro caminho seria awk '{sum+=$1} END {print sum}'
Se a lista de arquivos for muito grande e não puder ser passada para uma única invocação de du -c
, em um sistema GNU, você pode fazer:
find . -iname '*.jpg' -type f -printf '%b\t%D:%i\n' |
sort -u | cut -f1 | paste -sd+ - | bc
(tamanho expresso em número de blocos de 512 bytes). Como du
, ele tenta contar os links físicos apenas uma vez. Se você não se importa com hardlinks, pode simplificá-lo para:
(printf 0; find . -iname '*.jpg' -type f -printf +%b) | bc
Se você quiser o tamanho em vez do uso do disco, substitua %b
por %s
. O tamanho será então expresso em bytes.
As soluções mencionadas até agora são ineficientes (exec é caro) e requerem trabalho manual adicional para somar se a lista de arquivos for longa ou não funcionarem no Mac OS X. A solução a seguir é muito rápida, deve funcionar em qualquer sistema, e produz a resposta total em GB (remova a / 1024 se você quiser ver o total em MB):
find . -iname "*.jpg" -ls |perl -lane '$t += $F[6]; print $t/1024/1024/1024 . " GB"'
du naturalmente percorre a hierarquia de diretórios e o awk pode realizar a filtragem para que algo assim seja suficiente:
du -ak | awk 'BEGIN {sum=0} /\.jpg$/ {sum+=$1} END {print sum}'
Isso funciona sem o GNU.
Melhorando a ótima resposta da SHW para fazê-la funcionar com qualquer local, como Zbyszek já apontou em seu comentário:
LC_ALL=C find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$