Calcular o tamanho total do arquivo por extensão no shell


13

Temos um conjunto de diretórios contendo índices lucene. Cada índice é uma mistura de diferentes tipos de arquivos (diferenciados por extensão), por exemplo:

0/index/_2z6.frq
0/index/_2z6.fnm
..
1/index/_1sq.frq
1/index/_1sq.fnm
..

(são cerca de 10 extensões diferentes)

Gostaríamos de obter um total por extensão de arquivo, por exemplo:

.frq     21234
.fnm     34757
..

Eu tentei várias combinações de du / awk / xargs, mas acho difícil fazer exatamente isso.


Você tem a resposta para esse problema nesta postagem: serverfault.com/questions/183431/…
— Blueicefield 7/12/12

Deseja saber o tamanho total de cada tipo de arquivo ou o número total de cada tipo de arquivo?
— user9517

Tamanho total do arquivo, por favor.
— Barnybug # 03

Respostas:


19

Para qualquer extensão, você usa

find /path -name '*.frq' -exec ls -l {} \; | awk '{ Total += $5} END { print Total }'

para obter o tamanho total do arquivo para esse tipo.

E depois de pensar um pouco

#!/bin/bash

ftypes=$(find . -type f | grep -E ".*\.[a-zA-Z0-9]*$" | sed -e 's/.*\(\.[a-zA-Z0-9]*\)$/\1/' | sort | uniq)

for ft in $ftypes
do
    echo -n "$ft "
    find . -name "*${ft}" -exec ls -l {} \; | awk '{total += $5} END {print total}'
done

O que produzirá o tamanho em bytes de cada tipo de arquivo encontrado.


Obrigado, estava à procura de algo que resumido por qualquer extensão (como seria útil para em seguida, classificar por exemplo)
— barnybug

Verifique minha atualização.
— user9517

muito obrigado. awk produz produção científica para alguns dos números, isso pode ser desativado: .fdt 3.15152e + 10
— barnybug

1
ligeiramente ajustado para fornecer apenas números inteiros simples: encontre. -name "* $ {ft}" -print0 | xargs -0 du -c | total grep | awk '{print $ 1}'
— barnybug 7/03/2012

1
Pode querer usar -inamepara tornar a pesquisa de extensão de arquivo sem distinção entre maiúsculas e minúsculas.
— Aaron Copley

6

Com o bash version4, você só precisa chamar find, lse awknão é necessário:

declare -A ary

while IFS=$'\t' read name size; do 
  ext=${name##*.}
  ((ary[$ext] += size))
done < <(find . -type f  -printf "%f\t%s\n")

for key in "${!ary[@]}"; do 
  printf "%s\t%s\n" "$key" "${ary[$key]}"
done

Este script não funciona bem com nomes de arquivos com caractere de tabulação. Mudar read name sizepara read size namee -printf "%f\t%s\n"para -printf "%s\t%f\n"corrigi-lo.
— mate

1
Observe também que esse script não funciona bem com arquivos sem extensão. Ele tratará o nome completo do arquivo como extensão. Adicione if [ "$name" == "$ext" ]; then ext="*no_extension*"; fidepois ext=${name##*.}se precisar impedi-lo. Isto irá colocar todos os arquivos sem extensão em *no_extension*grupo (estou usando *no_extension*porque *não é um caractere válido em nome do arquivo)
— Matt

4

Cada segunda coluna dividida por .e última parte (extensão) salva na matriz.

#!/bin/bash

find . -type f -printf "%s\t%f\n" | awk '
{
 split($2, ext, ".")
 e = ext[length(ext)]
 size[e] += $1
}

END{
 for(i in size)
   print size[i], i
}' | sort -n

então você tem o tamanho total de todas as extensões em bytes.

60055 gemspec
321991 txt
2075312 html
2745143 rb
13387264 gem
47196526 jar

1

Estendendo o script de Iain com uma versão mais rápida para trabalhar com um grande número de arquivos.

#!/bin/bash

ftypes=$(find . -type f | grep -E ".*\.[a-zA-Z0-9]*$" | sed -e 's/.*\(\.[a-zA-Z0-9]*\)$/\1/' | sort | uniq)

for ft in $ftypes
do
    echo -ne "$ft\t"
    find . -name "*${ft}" -exec du -bcsh '{}' + | tail -1 | sed 's/\stotal//'
done


0

Eu resolvi usando estes dois comandos:

FILES=$(find . -name '*.c')
stat -c %s ${FILES[@]} | awk '{ sum += $1 } END { print ".c" " " sum }'

0

minha versão da resposta à pergunta:

#!/bin/bash

date >  get_size.log
# Lists all files
find . -type f -printf "%s\t%f\n" | grep -E ".*\.[a-zA-Z0-9]*$" | sort -h | awk  '
{
        split($2, ext, ".")
        e = ext[length(ext)]
        # Checks that one extension could be found
        if(length(e) < length($2)) {
                # Check that file size are bigger than 0
                if($i > 0) {
                        # Check that extension not are integer
                        if(!(e ~/^[0-9]+$/)) {
                                size[e] += $1
                        }
                }
        }
        if(length(e) == length($2)) {
                size["blandat"] += $1
        }
}

END{
 for(i in size)
   print size[i], i
}' | sort -n >> get_size.log
echo
echo
echo The result are in file get_size.log

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.