Encontre o tamanho total de certos arquivos em uma ramificação de diretório

115

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?

    
por mbaitoff 25.06.2012 / 06:38

9 respostas

148
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.

    
por 25.06.2012 / 08:15
42
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 )

    
por 25.06.2012 / 06:40
17

Primeiramente, você precisa de duas coisas:

  • a opção -c para du , para dizer que produz um total geral;
  • find ou ** para atravessar subdiretórios.
du -ch -- **/*.jpg | tail -n 1
    
por 26.06.2012 / 03:06
10

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:

  • todos os recursos de find para especificar os arquivos que você está procurando
  • suporta milhões de arquivos
    • outras respostas aqui são limitadas pelo tamanho máximo da lista de argumentos
  • gera apenas 3 processos simples com uma taxa de transferência mínima
    • muitas respostas aqui geram processos C + N, onde C é uma constante e N é o número de arquivos
  • não se incomoda com a manipulação de strings
    • esta versão não faz nenhum grepping ou regexing
    • bem, find faz uma correspondência simples de caracteres curinga de nomes de arquivos
  • formata opcionalmente a soma em um formato legível (por exemplo, 5.5K , 176.7M , ...)
    • para fazer isso, acrescente | numfmt --to=si
por 12.11.2016 / 17:54
7

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}'

    
por 05.08.2014 / 12:08
3

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.

    
por 05.08.2014 / 11:53
1

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"'

    
por 02.01.2016 / 01:17
1

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.

    
por 01.07.2016 / 09:58
0

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$
    
por 22.06.2016 / 09:55