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.