¿Cómo canalizar stdout mientras lo mantengo en la pantalla? (y no a un archivo de salida)

234

Me gustaría canalizar la salida estándar de un programa mientras lo mantengo en la pantalla.

Con un ejemplo simple (el echouso aquí es solo para fines ilustrativos):

$ echo 'ee' | foo
ee <- la salida que me gustaría ver

Sé que tee podría copiar stdout a un archivo, pero eso no es lo que quiero.
$ echo 'ee' | tee output.txt | foo

Lo intenté
$ echo 'ee' | tee /dev/stdout | foopero no funciona ya que la salida de tee /dev/stdoutse canaliza afoo

gentooboontoo
fuente
66
Sin echo 'ee' | tee /dev/stderrembargo, tenga en cuenta que funciona, por lo que si stderr también satisface su requisito "en pantalla" , eso funcionará.
nh2

Respuestas:

344

Aquí hay una solución que funciona en cualquier implementación de Unix / Linux, suponiendo que cumpla con el POSIXestándar. Funciona también en algunos entornos que no son Unix cygwin.

echo 'ee' | tee /dev/tty | foo

Referencia: The Open Group Base Especificaciones Número 7 IEEE Std 1003.1, Edición 2013, §10.1 :

/ dev / tty

Asociado con el grupo de procesos de ese proceso, si lo hay. Es útil para programas o procedimientos de shell que desean asegurarse de escribir mensajes o leer datos desde el terminal, sin importar cómo se haya redirigido la salida. También se puede usar para aplicaciones que exigen el nombre de un archivo para la salida, cuando se desea la salida escrita y es agotador saber qué terminal está actualmente en uso. En cada proceso, un sinónimo para el terminal de control

Se ha informado que algunos entornos como Google Colab no se implementan /dev/ttymientras que sus ttycomandos aún devuelven un dispositivo utilizable. Aquí hay una solución alternativa:

tty=$(tty)
echo 'ee' | tee $tty | foo

o con una antigua concha de Bourne:

tty=`tty`
echo 'ee' | tee $tty | foo
jlliagre
fuente
55
@static_rtti ¿Por qué ignoras año tras año mis respuestas a tu comentario?
jlliagre
1
@PaulBissex /dev/ttyes un dispositivo obligatorio de Unix. ¿Estás corriendo en una cárcel BSD?
jlliagre
1
@PaulBissex Eso es una implementación o un error de configuración. ¿Está / dev montado? ¿Qué muestra "ls -l / dev / tty / dev / tty * / dev"? Ver lists.freebsd.org/pipermail/freebsd-bugs/2012-November/… forums.freebsd.org/threads/…
jlliagre
1
Y puede conectarse en cascada de teeesta manera: cat some.log | tee /dev/tty | tee -a other.log | grep -i 'foo' >> foo.loga 1) llevarlo todo a la consola, 2) agregarlo todo a otro archivo, 3) llevar las foolíneas a un archivo diferente.
Jesse Chisholm
1
Google Colab no tiene /dev/tty, pero la salida de ttyes utilizable.
Tom Hale
69

Otra cosa para probar es:

echo 'ee' | tee >(foo)

El >(foo)es un proceso de sustitución .

bmk
fuente
1
¿Qué pasa si quiero canalizar la salida de foo a otra barra?
Jack Tang
3
@JackTang: creo que cualquier tubería adicional en la salida footendrá que ser parte de la sustitución del proceso. Aquí hay un ejemplo:echo 'ee' | tee file.txt >(wc -c | tr -d ' ')
Nick Chammas el
1
Esta fue la solución para mí en FreeBSD (no / dev / tty)
Paul Bissex
99
@ Nick Chammas, para mantener una tubería normal, que puede cambiar las salidas de camiseta: echo 'ee' | tee >(cat) | foo | bar.
Vaelus
18

El acceso a "/ dev / stdout" está denegado en algunos sistemas, pero el acceso al terminal de usuario está dado por "/ dev / tty". Usando "wc" para "foo", los ejemplos anteriores funcionan bien (en Linux, OSX, etc.) como:

% echo 'Hi' | tee /dev/tty | wc Hi 1 1 3

Para agregar un recuento al final de una lista de archivos coincidentes, utilizo algo como:
% ls [A-J]* | tee /dev/tty | wc -l

Para evitar tener que recordar todo esto, defino alias:
% alias t tee /dev/tty
% alias wcl wc -l

para que pueda simplemente decir:
% ls [A-J]* | t | wcl


POSTCRIPCIÓN: Para el conjunto más joven, que podría titularse en su pronunciación como "titty", podría agregar que "tty" fue la abreviatura común de un terminal "teletipo", que utilizaba un rollo de papel amarillo y tenía teclas redondas que a menudo atascado.

usuario51527
fuente
17

Tratar:

$ echo 'ee' | tee /dev/stderr | foo

Si usar stderr es una opción, por supuesto.

ene
fuente
8

primero debe averiguar el terminal asociado con su pantalla (o la pantalla en la que desea que se muestre la salida):

tty

entonces puede conectar la salida a esa terminal y canalizar la otra copia a través de su programa foo:

echo ee | tee /dev/pty/2 | foo
Michael Martinez
fuente
1
oneliner: t = $ (tty) echo ee | tee $ t | foo | bar
Jack Tang
55
@JackTang Eso es realmente mejor pero tes inútil. Puede usar, echo ee | tee $(tty) | foopero todavía tiene un comando inútil ( tty), dado que el hecho /dev/ttysimplemente funciona.
jlliagre