ls com find :: tamanho total do relatório

5

Estou tentando obter o tamanho total dos arquivos que satisfazem um find , por exemplo:

ls  $(find -maxdepth 2 -type f)

No entanto, esse tipo de invocação de ls também não produz o tamanho total.

    
por Marcus Junius Brutus 05.12.2013 / 13:36

6 respostas

6

Acredite ou não, você pode fazer isso com find e du . Eu usei uma técnica semelhante que escrevi no meu blog um pouco. Esse artigo é intitulado: [one-liner ]: Calculando o uso do espaço em disco para uma lista de arquivos usando o du no Linux .

A essência desse post é um comando como este:

$ find -maxdepth 2 -type f | tr '\n' '
$ find -maxdepth 2 -type f | tr '\n' '
--files0-from=F
          summarize disk usage of the NUL-terminated file names specified in 
          file F; If F is - then read names from standard input
' | du -ch --files0-from=- | tail -10 0 ./92086/2.txt 0 ./92086/5.txt 0 ./92086/14.txt 0 ./92086/19.txt 0 ./92086/18.txt 0 ./92086/17.txt 4.0K ./load.bash 4.0K ./100855/plain.txt 4.0K ./100855/tst_ccmds.bash 21M total
' | du -ch --files0-from=-

Exemplo

Isso listará o tamanho de todos os arquivos junto com um total de resumo.

du: cannot access './101415/fileD': No such file or directory
du: cannot access 'E': No such file or directory

OBSERVAÇÃO: Essa solução requer que du suporte a opção --files0-from= , que é um switch GNU, que eu saiba.

trecho da página du man

$ find -maxdepth 2 -type f -print0 | du -ch --files0-from=- | tail -10
0   ./92086/2.txt
0   ./92086/5.txt
0   ./92086/14.txt
0   ./92086/19.txt
0   ./92086/18.txt
0   ./92086/17.txt
4.0K    ./load.bash
4.0K    ./100855/plain.txt
4.0K    ./100855/tst_ccmds.bash
21M total

Além disso, esse método sofre com a impossibilidade de lidar com caracteres especiais em nomes de arquivos, como espaços e não-imprimíveis.

Exemplos

$ find -maxdepth 2 -type f | tr '\n' '
$ find -maxdepth 2 -type f | tr '\n' '
--files0-from=F
          summarize disk usage of the NUL-terminated file names specified in 
          file F; If F is - then read names from standard input
' | du -ch --files0-from=- | tail -10 0 ./92086/2.txt 0 ./92086/5.txt 0 ./92086/14.txt 0 ./92086/19.txt 0 ./92086/18.txt 0 ./92086/17.txt 4.0K ./load.bash 4.0K ./100855/plain.txt 4.0K ./100855/tst_ccmds.bash 21M total
' | du -ch --files0-from=-

Isso pode ser resolvido com a introdução de mais comandos tr .. .. para substituí-los por caracteres alternativos. No entanto, existe uma maneira melhor, se você tiver acesso ao find do GNU.

Melhorias

Se a sua versão de find oferecer a opção --print0 , você poderá usar esse encantamento que lida com arquivos que possuem espaços e / ou caracteres especiais que não podem ser impressos.

du: cannot access './101415/fileD': No such file or directory
du: cannot access 'E': No such file or directory
    
por 05.12.2013 / 15:30
6

du (uso do disco) conta os arquivos de espaço ocupados. Transmita seus arquivos encontrados para ele e direcione-o para resumir ( -c ) e imprima em um formato legível por humanos ( -h ) em vez de contagens de bytes. Então, os tamanhos de todos os arquivos serão concluídos com um total geral. Se você está interessado apenas nesta última linha, então você pode tail para isso.

Para também manipular espaços em nomes de arquivos, o símbolo de delimitação que find imprime e xargs espera é definido como o símbolo nulo em vez do espaço usual.

find -maxdepth 2 -type f -print0 | xargs -0 du -ch | tail -n1

Se você espera encontrar muitos arquivos que rebentam o número máximo de argumentos, os xargs os dividirão em várias invocações du . Então você poderia contornar com a substituição de tail por um grep , que mostra apenas as linhas de resumo.

find -maxdepth 2 -type f -print0 | xargs -0 du -ch | grep -P '\ttotal$'
    
por 05.12.2013 / 13:39
3

Outra abordagem: só precisamos do tamanho do arquivo, e não nos importamos com os nomes dos arquivos, para que possamos nos livrar de qualquer nome de arquivo "esquisito", como "nomes com CR neles, nomes com espaços, etc" :

 find /some/path -maxdepth 2 -type f -ls -exec printf '
 find /some/path -maxdepth 2 -type f -ls -exec printf '%pre%0' \; \
     | tr -cd ' -~%pre%0' \
     | tr '%pre%0' '\n'   \
     | awk  '{ sum+=$7 } END { print "total size: ",sum }'
0' \; \ | tr -cd ' -~%pre%0' \ | tr '%pre%0' '\n' \ | awk '{ sum+=$7 } END { print "total size: ",sum }'

O truque é:

1) imprimimos a saída "-ls" de cada arquivo, SEGUIDA por um caracter "\ 000" (na próxima linha, mas isso não é um problema, veja o passo 2)
  2) nos livramos de tudo 'não-imprii-print' (incluindo '\ t' e '\ n'. Mas também mantemos o \ 000 para o ASCII imprimível "regular", pois precisamos saber onde a linha de cada arquivo termina! Dessa forma, os nomes de arquivos não têm mais nenhuma peculiaridade neles (sem '\ n', no '\ t', no ';', etc). Mantemos os espaços também, pois também precisamos deles para descobrir o sétimo campo de "-ls", ou seja, o tamanho do arquivo.  3) nós traduzimos o '\ 000' em um '\ n' (passo 2) também nos livramos daqueles, caso alguns nomes de arquivos também os contenham!)
 4) então adicionamos a 7ª coluna para obter o tamanho final em bytes.

Isto é muito portátil (não precisa de "-print0", etc)

    
por 05.12.2013 / 15:15
2

Se você só vai calcular o tamanho máximo de dois níveis de diretório, por que não chamar du diretamente?

du -ch dir/* dir/*/* | tail -1

Isso faz com que o shell expanda os dois níveis de diretórios para uma lista de nomes e os transmita como argumentos para du , que calcula a soma.

    
por 05.12.2013 / 16:04
1

find -maxdepth 2 -type f --print0 | xargs -0 du -ch

    
por 05.12.2013 / 13:43
0

Esta é uma maneira simples que lida com qualquer nome de arquivo estranho que possa ser encontrado:

find . -maxdepth 2 -type f -exec du -ch {} + | grep -w "total"

Se houver um número realmente grande de arquivos no diretório atual, você poderá ter mais de uma linha total exibida. Também pode haver linhas totais indesejadas se alguns nomes de arquivo contiverem um " total " isolado, por exemplo: um arquivo chamado " Grand total file.txt "

    
por 05.12.2013 / 15:46

Tags