Soma do tamanho do arquivo de uma lista de arquivos

5

Eu tenho um arquivo de texto que contém uma lista de nomes de arquivos (um nome de arquivo por linha).

Agora eu gostaria de calcular o tamanho de todos esses arquivos. Eu acho que vou ter que fazer um ls -la em cada linha do arquivo e depois acumular o tamanho do arquivo.

Acho que awk fará parte da solução, mas é só adivinhar.

    
por Tobias Gassmann 05.10.2015 / 14:46

6 respostas

11

Com o GNU stat :

stat -c %s -- $(<list) | paste -d+ -s - | bc
  • stat exibe informações sobre o arquivo
    • -c especifica o formato, %s fornece o tamanho do arquivo em bytes
  • paste -d+ -s concatia a saída juntos linha por linha com um + como delimitador
  • bc canalizado para bc , será calculado em conjunto.

Adicione uma opção -L a stat , se para links simbólicos, você preferiria contar o tamanho do arquivo que o symlink eventualmente resolveu.

Isso pressupõe um shell como ksh , bash ou zsh com o operador $(<file) para invocar split + glob no conteúdo de um arquivo.

Aqui, espera-se que list seja um espaço, tabulação ou nova linha (supondo o valor padrão de $IFS ), uma lista delimitada de padrões de arquivo (como em *.txt /bin/* ). Para uma lista de caminhos de arquivo, um por linha, você precisaria desabilitar o globbing e limitar o $IFS somente para a nova linha ou com o GNU xargs :

xargs -rd '\n' -a list stat -c %s -- | paste -sd+ - | bc
    
por 05.10.2015 / 14:55
6

Você precisa da última linha de du -c output

du -ch $(<list) | tail -1
    
por 05.10.2015 / 14:58
5

Eu usaria o teste de arquivo -s e perl :

-s File has nonzero size (returns size in bytes).

Algo parecido com isto:

#!/usr/bin/env perl;
use strict;
use warnings;

my $sum = 0;
while ( my $filename = <> ) {
    chomp ( $filename );
    $sum += -s $filename;
}

print "Sum is $sum bytes\n";

(lê nomes de arquivos de STDIN ou de um arquivo especificado na linha de comando, por exemplo, myscript.pl file_list.txt )

Você poderia "um forro":

perl -nle '$sum += -s $_; END { print $sum }'

(e um pipe em uma 'lista de nomes de arquivos' ou especifique um argumento de arquivo como antes)

    
por 05.10.2015 / 14:53
0

Eu também encontrei uma solução:

cat files.txt | while read f; do ls -la $f; done | awk '{s+=$5;} END {print s;}'
    
por 05.10.2015 / 15:02
0

Outra alternativa, usando comandos comuns do shell. Até lida com o caso filename-with-spaces. Presume que a lista de nomes de arquivos esteja em um arquivo chamado fnames .

tr '\n' '
tr '\n' '%pre%' < fnames | xargs -0 cat | wc -c
' < fnames | xargs -0 cat | wc -c

wc é incrivelmente útil na contagem de situações. Tenha isso em mente.

    
por 05.10.2015 / 19:10
0

Para nomes de arquivos com espaço na minha lista, usei isso (inspirado na resposta do @Costas):

SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
du -ch $(<list) |tail -1
IFS=$SAVEIFS
    
por 31.10.2017 / 11:54

Tags