¿Cómo mostrar el número de líneas generadas por un comando en tiempo real?

15

Estoy usando svn exportcomo parte de un script de empaquetador para mi aplicación, y parece que este comando, como muchos otros, no tiene ningún tipo de barra de progreso.

Tengo dos opciones en este momento:

  • usarlo sin opciones y verlo imprimir miles de líneas
  • usando --quiety sin ver nada hasta que se complete.

¿Hay alguna manera de mostrar al menos el número de líneas que genera el comando en tiempo real? Como:

Exporting SVN directory ... 1234 files

¿Y ves este 1234 incremento de número en tiempo real ? Me imagino canalizando la salida a un comando que haría exactamente esto, pero ¿cuál?

Benjamín
fuente

Respuestas:

16
yourcommand | { I=0; while read; do printf "$((++I))\r"; done; echo ""; }

O ponga la sección entre corchetes en un script de shell. Tenga en cuenta que esto solo funciona si su shell realmente admite el operador de preincremento, como bash o ksh93 o zsh. De lo contrario, tendrá que incrementar $Iy luego imprimirlo (como en I=$((I+1));printf...). Además, si printfno está integrado con su caparazón (es uno incorporado con bash actual), puede usarlo echo -neo, en print -ncambio, para un mejor rendimiento. Solo desea suprimir la nueva línea e interpretar el \ r como un carácter de escape.

dannysauer
fuente
Oh, nunca me obligaré a aprender bashscripting con todas sus =diferencias y peculiaridades feas y `=`. :) ¿Por qué no lo reemplazarían con lenguaje sintaxis similar a python ...
Boris Burkov
¡Hola, lo sé! Puede agregar el símbolo de retorno de carro a cada nueva línea que imprima, y ​​no inundará la pantalla, simplemente sobrescribirá la línea anterior.
Boris Burkov
Es por eso que printftermina con a \r. Y qué pasa si lo haces echo -ne "$I\r"o print -n "$I\r". :) printfSin embargo, solía , porque el valor predeterminado es no imprimir una nueva línea al final, por lo que \rsolo retrocede al principio. Desafortunadamente, no todas las implementaciones de eco admiten el argumento -eo -n.
dannysauer
1
Esto también funciona con la versión pdksh que OpenBSD usa para / bin / sh.
kurtm
1
+1, aunque para ser absolutamente correcto, debe cambiar reada read -r(ya que, de lo contrario, una barra invertida al final de una línea alteraría el conteo). Por cierto, con un poco de trabajo, esto se puede adaptar para mostrar también la última línea de salida, que puede ser útil para algunos comandos.
ruakh
7

Esta es una idea aproximada, pero podría usar el pvcomando para contar el número de líneas a medida que pasan y mostrarlo en la pantalla. pvEntre sus muchos interruptores tiene un -linterruptor que cuenta cada línea a medida que avanza.

Ejemplo

Aquí estoy usando un ciclo while para simular algunos archivos de su salida SVN.

$ for i in $(seq 100); do echo "file$i"; sleep 2; done | pv -l -c >/dev/null
   3 0:00:05 [0.99/s ] [      <=>             

Seguirá sobrescribiendo la línea de salida de esta manera:

  18 0:00:36 [   0/s ] [                                     <=>                                                                  ]

  24 0:00:47 [0.991/s ] [                                                <=>                                                      ]
slm
fuente
No estaba al tanto de pv. ¡Hurra por aprender cosas!
dannysauer
@dannysauer: vale la pena pasar un tiempo aprendiendo pv, ya que permite medir y mostrar todo lo que pasa por una tubería.
slm
Lo instalé después de leer el comentario y jugar con él. Dieciocho años usando Linux, y siempre hay cosas nuevas por descubrir. :)
dannysauer
0

Puede ejecutar su comando en segundo plano como un trabajo y redirigir su stdout (y stderr opcionalmente) a un archivo de registro: command > logfile &donde &designa el trabajo (si es stderr también, diga en &>lugar de >).

Luego puede usar la utilidad de conteo de palabras para contar la cantidad de líneas en su archivo de registro wc -l.

Para mostrar el cambio de estado en una línea que cambia dinámicamente, podría usar algo como while true; do echo -en '\r'; wc -l logfile; sleep 1; done, pero no puedo obligar a bash a dibujar el \rretorno del carro para eliminar el contenido de la línea anterior.

Vea esta pregunta, es casi un duplicado: /programming/2388090/how-to-delete-and-replace-last-line-in-the-terminal-using-bash

Boris Burkov
fuente
1
Pero él quiere una pantalla en tiempo real que siga incrementándose, que no es lo que hace wc.
kurtm
@kurtm eh, lo que quiere mucho más es no inundar su pantalla con los resultados de printf/print/echolo sugerido por danny. :) Por supuesto, podría usarlo less, pero supongo que puede darse el lujo de decir wc -l logfilecada vez que se impacienta. Creo que jugar con ncurseso borrar la pantalla es una exageración aquí.
Boris Burkov
Bueno, sí. No quiere que se inunde, pero quiere saber el progreso, de lo contrario, podría usar el silencio.
kurtm
@kurtm ver actualización: ¿puedes ayudar a depurar mi echo -e 'r'comando? Debería borrar el contenido de línea previamente impreso, para que cambie dinámicamente, pero no puedo obligarlo a hacerlo :(
Boris Burkov
También desea agregar la opción n para hacer eco que suprime la nueva línea final.
kurtm