Como fazer um 'wc -l' contínuo com o gnu texttools?

24

Eu sei, claro, que

cat logfile.txt | wc -l
120

me informará o número de linhas em um arquivo.

Considerando que

tail -f logfile.txt

mostrará as novas linhas que outro programa grava em logfile.txt .

É possível combinar os dois para obter uma contagem de linha de atualização contínua de logfile.txt com utilitários de texto padrão?

Eu sei sobre

watch wc -l logfile.txt

mas eu não quero recontar o arquivo inteiro a cada vez, isso parece ser um desperdício. Alguém precisaria de uma contagem somente de anexos a cada segundo ou mais e provavelmente um \r em vez de um \n no final da linha.

    
por towi 19.02.2013 / 13:48

4 respostas

32

Talvez:

tail -n +1 -f file | awk '{printf "\r%lu", NR}'

Tenha em atenção que o resultado seria um número para cada linha de entrada (apesar de substituir o valor anterior se enviado para um terminal).

Ou você pode implementar o tail -f manualmente no shell:

n=0
while :; do 
  n=$(($n + $(wc -l)))
  printf '\r%s' "$n"
  sleep 1
done < file

(observe que ele executa até um comando wc e um sleep por segundo que nem todos os shells criaram. Com ksh93 , enquanto sleep está embutido, para obter um wc integrado ( pelo menos no Debian), você precisa adicionar /opt/ast/bin na frente de $PATH (independentemente de existir ou não esse diretório) ou usar command /opt/ast/bin/wc (não pergunte ...)).

Você pode usar pv , como em:

tail -n +1 -f file | pv -bl > /dev/null

Mas cuidado, pois ele adiciona k , M ... sufixos quando o número é superior a 1000 (e não parece haver uma maneira de contornar isso ).

    
por 19.02.2013 / 14:01
5

Tente contabilizá-lo com bash sem wc :

a=0 ; tail -f file | while read -r line ; do ((a++)) ; echo $a ; done

ou até mesmo assim para reescrever o valor anterior:

a=0 ; tail -f file | while read -r line ; do ((a++)) ; echo -ne "\r$a" ; done
    
por 19.02.2013 / 13:59
1

Eu não acredito que haja algo assim. Mas deve ser fácil fazer algo como:

#!/usr/bin/perl

$for_a_while = 1;

$oldcount = -1;
$count = 0;
open($fh, "<", $ARGV[0]);

for (;;) {
  for ($curpos = tell($fh); <$fh>; $curpos = tell($fh)) {
    $count++;
  }
  if($count != $oldcount) {
    print "$count\n";
    $oldcount = $count;
  }
  sleep($for_a_while);
  seek($fh, $curpos, 0);
}

(Idéia genérica extraída de perlfunc(1) )

    
por 19.02.2013 / 15:52
0

Continuando a solução baseada no awk: talvez você não precise ver o contador de cada linha no seu log; esse é o caso, você pode ter isso assim (o número mudaria para cada 10 linhas):

tail -n +0 logfile.txt | \
    awk 'a+=1{}a%10==0{printf "\r%lu", a}END{printf "\r%lu", a}'
    
por 19.02.2013 / 22:11