Como encontrar o tamanho total do arquivo agrupado por extensão

7

Eu trabalho em um cluster compartilhado com outros colegas. O disco rígido é limitado (e está cheio em algumas ocasiões), então eu limpo minha parte ocasionalmente. Eu quero fazer isso rapidamente, então até agora eu faço isso fazendo uma lista de arquivos maiores que 100 MB com mais de 3 meses, e vejo se ainda preciso deles.

Mas agora estou pensando que poderia haver uma pasta com > 1000 arquivos menores que eu sinto falta, por isso quero ter uma maneira fácil de ver se esse é o caso. Do jeito que eu gero dados, ajudaria a obter uma lista do tamanho total por extensão. No contexto desta questão, 'extensão' como tudo por trás do último ponto no nome do arquivo.

Suponha que eu tenha várias pastas com vários arquivos:

folder1/file1.bmp   40 kiB
folder1/file2.jpg   20 kiB
folder2/file3.bmp   30 kiB
folder2/file4.jpg    8 kiB

É possível fazer uma lista do tamanho total do arquivo por extensão, assim:

bmp 70 kiB
jpg 28 kiB

Eu não me importo com arquivos sem extensão, então eles podem ser ignorados ou colocados em uma categoria.

Já passei pelas man pages de ls , du e find , mas não sei qual é a ferramenta certa para esse trabalho ...

    
por Pakk 09.09.2016 / 12:11

3 respostas

9

Em um sistema GNU:

find . -name '?*.*' -type f -printf '%b.%f
find . -name '?*.*' -type f -print0 |
  perl -0ne '
    if (@s = stat$_){
      ($ext = $_) =~ s/.*\.//s;
      $s{$ext} += $s[12];
      $n{$ext}++;
    }
    END {
      for (sort{$s{$a} <=> $s{$b}} keys %s) {
        printf "%15d %4d %s\n",  $s{$_}<<9, $n{$_}, $_;
      }
    }'
' | awk -F . -v RS='
          12288    1 pnm
          16384    4 gif
         204800    2 ico
        1040384   17 jpg
        2752512   83 png
' ' {s[$NF] += $1; n[$NF]++} END {for (e in s) printf "%15d %4d %s\n", s[e]*512, n[e], e}' | sort -n

Ou o mesmo com perl , evitando a extensão -printf do GNU find (ainda usando uma extensão GNU, -print0 , mas essa é mais amplamente suportada hoje em dia):

find . -name '?*.*' -type f -printf '%b.%f
find . -name '?*.*' -type f -print0 |
  perl -0ne '
    if (@s = stat$_){
      ($ext = $_) =~ s/.*\.//s;
      $s{$ext} += $s[12];
      $n{$ext}++;
    }
    END {
      for (sort{$s{$a} <=> $s{$b}} keys %s) {
        printf "%15d %4d %s\n",  $s{$_}<<9, $n{$_}, $_;
      }
    }'
' | awk -F . -v RS='
          12288    1 pnm
          16384    4 gif
         204800    2 ico
        1040384   17 jpg
        2752512   83 png
' ' {s[$NF] += $1; n[$NF]++} END {for (e in s) printf "%15d %4d %s\n", s[e]*512, n[e], e}' | sort -n

Ele fornece uma saída como:

%pre%

Se você quiser KiB , MiB ... sufixos, canalizar para numfmt --to=iec-i --suffix=B .

%b*512 fornece o uso do disco, mas observe que, se os arquivos forem vinculados várias vezes, eles serão contados várias vezes, portanto você poderá ver uma discrepância com o que du reporta.

    
por 09.09.2016 / 12:39
2

Aqui está outra solução:

find . -type f |  egrep -o "\.[a-zA-Z0-9]+$" | sort -u | xargs -I '%' find . -type f -name "*%" -exec du -ch {} + -exec echo % \; | egrep "^\.[a-zA-Z0-9]+$|total$" | uniq | paste - -

A parte que recebe as extensões é:

find . -type f |  egrep -o "\.[a-zA-Z0-9]+$" | sort -u

Em seguida, pesquise os arquivos com uma extensão e imprima-os também na tela:

xargs -I '%' find . -type f -name "*%" -exec du -ch {} + -exec echo % \;

Em seguida, queremos manter a extensão e o total:

egrep "^\.[a-zA-Z0-9]+$|total$" | uniq

e mantenha-o na mesma linha:

paste - -
    
por 19.07.2018 / 17:10
1

Não tão legal quanto a solução de Stephane, mas você poderia tentar

find . -type f -name "*.png" -print0 | xargs -0r du -ch | tail -n1

onde você precisa executar isso para cada tipo de arquivo.

    
por 09.09.2016 / 12:54