How to pipe stdout while keeping it on screen ? (and not to a output file) How to pipe stdout while keeping it on screen ? (and not to a output file) bash bash

How to pipe stdout while keeping it on screen ? (and not to a output file)


Here is a solution that works at on any Unix / Linux implementation, assuming it cares to follow the POSIX standard. It works on some non Unix environments like cygwin too.

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

Reference: The Open Group Base Specifications Issue 7IEEE Std 1003.1, 2013 Edition, ยง10.1:

/dev/tty

Associated with the process group of that process, if any. It is useful for programs or shell procedures that wish to be sure of writing messages to or reading data from the terminal no matter how output has been redirected. It can also be used for applications that demand the name of a file for output, when typed output is desired and it is tiresome to find out what terminal is currently in use. In each process, a synonym for the controlling terminal

Some environments like Google Colab have been reported not to implement /dev/tty while still having their tty command returning a usable device. Here is a workaround:

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

or with an ancient Bourne shell:

tty=`tty`echo 'ee' | tee $tty | foo


Another thing to try is:

echo 'ee' | tee >(foo)

The >(foo) is a process substitution.

Edit:
To make a bit clearer, (.) here start a new child process to the current terminal, where the output is being redirected to.

echo ee | tee >(wc | grep 1)#              ^^^^^^^^^^^^^^ => child process

Except that any variable declarations/changes in child process do not reflect in the parent, there is very few of concern with regard to running commands in a child process.


Try:

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

If using stderr is an option, of course.