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.

barnybug
fonte
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.

Iain
fonte
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
Glenn Jackman
fonte
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
Selman Ulug
fonte
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
MilesF
fonte
0

Eu resolvi usando estes dois comandos:

FILES=$(find . -name '*.c')
stat -c %s ${FILES[@]} | awk '{ sum += $1 } END { print ".c" " " sum }'
c4f4t0r
fonte
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
Isterklister
fonte
0

Experimente o Crab ( http://etia.co.uk/ ) - é um utilitário de linha de comando que permite consultar o sistema de arquivos usando o SQL.

Jacek Lampart
fonte