Gerar distribuição de tamanhos de arquivo a partir do prompt de comando

13

Eu tenho um sistema de arquivos que tem alguns milhões de arquivos e gostaria de ver uma distribuição de tamanhos de arquivos de forma recursiva em um diretório específico. Eu sinto que isso é totalmente factível com algum fu bash / awk, mas poderia usar uma mão. Basicamente eu gostaria de algo como o seguinte:

1KB: 4123
2KB: 1920
4KB: 112
...
4MB: 238
8MB: 328
16MB: 29138
Count: 320403345

Eu sinto que isso não deveria ser muito ruim, dado um loop e alguns arquivos log2 condicionais foo, mas eu não consigo chegar lá.

Questão relacionada: Como pode Eu acho arquivos maiores / menores que x bytes? .

    
por notpeter 13.03.2013 / 19:31

3 respostas

15

Isso parece funcionar muito bem:

find . -type f -print0 | xargs -0 ls -l | awk '{size[int(log($5)/log(2))]++}END{for (i in size) printf("%10d %3d\n", 2^i, size[i])}' | sort -n

Sua saída é assim: %código% onde o número à esquerda é o limite inferior de um intervalo desde aquele valor até o dobro desse valor e o número à direita é o número de arquivos nesse intervalo.

    
por 13.03.2013 / 20:08
6

Com base na resposta de garyjohn, aqui está um one-liner, que também formata a saída para legível:

find . -type f -print0 | xargs -0 ls -l | awk '{ n=int(log($5)/log(2)); if (n<10) { n=10; } size[n]++ } END { for (i in size) printf("%d %d\n", 2^i, size[i]) }' | sort -n | awk 'function human(x) { x[1]/=1024; if (x[1]>=1024) { x[2]++; human(x) } } { a[1]=$1; a[2]=0; human(a); printf("%3d%s: %6d\n", a[1],substr("kMGTEPYZ",a[2]+1,1),$2) }'

Aqui está a versão expandida:

find . -type f -print0                                                   \ 
 | xargs -0 ls -l                                                        \
 | awk '{ n=int(log($5)/log(2));                                         \
          if (n<10) n=10;                                                \
          size[n]++ }                                                    \
      END { for (i in size) printf("%d %d\n", 2^i, size[i]) }'           \
 | sort -n                                                               \ 
 | awk 'function human(x) { x[1]/=1024;                                  \
                            if (x[1]>=1024) { x[2]++;                    \
                                              human(x) } }               \
        { a[1]=$1;                                                       \ 
          a[2]=0;                                                        \
          human(a);                                                      \
          printf("%3d%s: %6d\n", a[1],substr("kMGTEPYZ",a[2]+1,1),$2) }' 

No primeiro awk defini um tamanho de arquivo mínimo para coletar todos os arquivos com menos de 1kb em um único lugar. No segundo awk , a função human(x) é definida para criar um tamanho legível para humanos. Esta parte é baseada em uma das respostas aqui: link

A saída de amostra é semelhante a:

  1k:    335
  2k:     16
 32k:      5
128k:     22
  1M:     54
  2M:     11
  4M:     13
  8M:      3
    
por 13.07.2016 / 14:36
2

Tente isto:

find . -type f -exec ls -lh {} \; | 
 gawk '{match($5,/([0-9.]+)([A-Z]+)/,k); if(!k[2]){print "1K"} \
        else{printf "%.0f%s\n",k[1],k[2]}}' | 
sort | uniq -c | sort -hk 2 

OUTPUT:

 38 1K
 14 2K
  1 30K
  2 62K
  12 2M
  2 3M
  1 31M
  1 46M
  1 56M
  1 75M
  1 143M
  1 191M
  1 246M
  1 7G

EXPLICAÇÃO:

  • find . -type f -exec ls -lh {} \; : simples, encontre arquivos no diretório atual e execute ls -lh neles

  • match($5,/([0-9.]+)([A-Z]+)/,k); : isso extrairá o tamanho do arquivo e salvará cada correspondência na matriz k .

  • if(!k[2]){print "1K"} : se k[2] for indefinido, o tamanho do arquivo será < 1K. Como imagino que você não se importa com esses tamanhos minúsculos, o script imprimirá 1K para todos os arquivos cujo tamanho seja < = 1K.

  • else{printf "%.0f%s\n",k[1],k[2]} : se o arquivo for maior que 1K, arredonde o tamanho do arquivo para o inteiro mais próximo e imprima junto com seu modificador (K, M ou G).

  • sort | uniq -c : conta as ocorrências de cada linha (tamanho do arquivo) impressas.

  • sort -hk 2 : classifica de acordo com o segundo campo em formato legível por humanos. Dessa forma, 7G é classificado após 8M .

por 13.03.2013 / 19:51