Como medir o tamanho dos dados canalizados?

16

Eu gostaria de fazer algo assim:

> grep pattern file.txt | size -h
16.4 MB

ou algo equivalente a:

> grep pattern file.txt > grepped.txt
> ls -h grepped.txt
16.4 MB
> rm grepped.txt

(isso seria um pouco inconveniente)

Isso é possível?

Raffael
fonte

Respostas:

32

Você pode usar wcpara isso:

grep pattern file.txt | wc -c

contará o número de bytes na saída. Você pode pós-processar isso para converter valores grandes em formato "legível por humanos" .

Você também pode usar pvpara obter essas informações dentro de um pipe:

grep pattern file.txt | pv -b > output.txt

(isso exibe o número de bytes processados, em formato legível por humanos).

Stephen Kitt
fonte
1
Eu prefiro wc -cporque du -hretorna `4.0 k` se é qualquer menor que 4,0k como se lê em blocos
Stan Strum
Se imprimir a saída em MB for suficiente, o comando pode ser | wc -c | sed 's/$/\/1024\/1024/' | bc. Isso anexa /1024/1024à saída e executa uma calculadora na sequência resultante.
phil294
9

Você pode usar a ferramenta pipeviewer pvcom o sinalizador de contagem total de bytes -b:

$ dd if=/dev/zero bs=3 count=4211 2>/dev/null | pv -b >/dev/null
12.3KiB

$ grep pattern file.txt | pv -b >/dev/null
Bjarke Freund-Hansen
fonte
3

O utilitário Pipe Viewer foi projetado para essa finalidade. Se não for flexível o suficiente para seus propósitos, você poderá implementar seu próprio código de medição de transferência de dados FIFO com as chamadas de função da biblioteca de manipulação de pipeline ( libpipeline ), como pipeline_pump()e pipeline_peek_size().

$ whatis pv
pv (1)               - monitor the progress of data through a pipe
$ pv -Wi 0.002 -cf /etc/hosts | wc -l
 367 B 0:00:00 [2.71MiB/s] 
[============================================================================>] 
100%
10
$
Derek Callaway
fonte
1

Pode-se preparar rapidamente sua própria solução em Python:

#!/usr/bin/env python
import sys

count = 0
while True:
    byte = sys.stdin.read(1)
    if not byte:
        break
    count =  count + 1

print(count)

Funciona assim:

$ echo "Hi" | ./count_stdin_bytes.py
3
$ echo "Hello" | ./count_stdin_bytes.py
6
$ dd if=/dev/zero bs=1 count=1024 2>/dev/null |  ./count_stdin_bytes.py 
1024

Como no seu caso particular, você está lidando com dados de texto (a julgar pelo fato de ser do qual é o canal grep), você também pode usar os bash's read. Algo assim:

$ echo "Hello" | { while read -n 1 char; do ((count++)) ;done ; echo $count; }
6
Sergiy Kolodyazhnyy
fonte
Por que isso é melhor do que wc -c? while read ...provavelmente será significativamente mais lento. Além disso, o OP solicitou uma saída legível como em ( ls -h)
phil294