¿Cómo medir el tamaño de los datos canalizados?

16

Me gustaría hacer algo como esto:

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

o algo equivalente a:

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

(aunque eso sería un poco incómodo)

¿Es eso posible?

Raffael
fuente

Respuestas:

32

Puedes usar wcpara esto:

grep pattern file.txt | wc -c

contará el número de bytes en la salida. Puede postprocesar eso para convertir valores grandes a formato "legible para humanos" .

También puede usar pvpara obtener esta información dentro de una tubería:

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

(esto muestra el número de bytes procesados, en formato legible por humanos).

Stephen Kitt
fuente
1
Prefiero wc -cporque du -hdevuelve `4.0 K` si es más pequeño que 4,0k mientras lee en bloques
Stan Strum
Si imprimir el resultado en MB es suficiente, el comando podría serlo | wc -c | sed 's/$/\/1024\/1024/' | bc. Esto se agrega /1024/1024a la salida y ejecuta una calculadora en la cadena resultante.
phil294
9

Puede utilizar la herramienta pipeviewer pvcon la bandera recuento 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
fuente
3

La utilidad Pipe Viewer fue diseñada para este propósito. Si no es lo suficientemente flexible para sus propósitos, puede implementar su propio código de medición de transferencia de datos FIFO con las llamadas a funciones de la biblioteca de manipulación de tuberías ( libpipeline ) como pipeline_pump()y 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
fuente
1

Uno podría elaborar rápidamente su propia solución en 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 así:

$ 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

Dado que en su caso particular se trata de datos de texto (a juzgar por el hecho de que realiza la canalización grep), también puede hacer uso de bash's read. Algo como esto:

$ echo "Hello" | { while read -n 1 char; do ((count++)) ;done ; echo $count; }
6
Sergiy Kolodyazhnyy
fuente
¿Por qué es esto mejor que wc -c? while read ...probablemente será significativamente más lento. Además, OP solicitó una salida legible para humanos como en ( ls -h)
phil294