如何管道stdout,同时保持它在屏幕上?(而不是输出文件)

我想管道标准输出的程序,同时保持它在屏幕上。

通过一个简单的例子(这里使用echo只是为了说明):

< p > $ echo 'ee' | foo < br > ee <-输出我想看到

我知道tee可以复制标准输出到文件,但这不是我想要的 $ echo 'ee' | tee output.txt | foo < / p > < br > < p >我试着 $ echo 'ee' | tee /dev/stdout | foo,但它不工作,因为tee输出到/dev/stdout是管道到foo

97322 次浏览

下面是一个适用于任何Unix / Linux实现的解决方案,假设它关心遵循POSIX标准。它也适用于一些非Unix环境,比如cygwin

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

参考:开放组基础规范第7期 IEEE Std 1003.1, 2013 Edition,§10.1:

/dev/tty

如果有,与该进程的进程组关联。< >强 对于希望确定的程序或shell过程很有用 无论如何向写入消息或从读取数据 输出已重定向。也可以用于 当需要输入输出时,要求输出文件的名称 查找当前正在使用的终端是一件令人厌烦的事情。在每个进程中,控制终端的同义词

据报道,一些环境,如谷歌Colab,没有实现/dev/tty,但仍然有他们的tty命令返回一个可用的设备。这里有一个变通办法:

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

或者用古老的伯恩壳:

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

试一试:

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

当然,如果可以选择使用stderr。

另一件可以尝试的事情是:

echo 'ee' | tee >(foo)

>(foo)是一个进程替换

< p > 编辑: < br > 为了更清楚一点,(.)在这里启动一个新的子进程到当前终端,输出被重定向到。

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

除了子进程中的任何变量声明/更改都不会反映在父进程中之外,在子进程中运行命令几乎没有什么需要关注的。

首先,你需要找出与你的屏幕(或任何你想在屏幕上显示输出的屏幕)相关的终端:

tty

然后你可以将输出tee到该终端,并通过你的foo程序管道另一个副本:

echo ee | tee /dev/pty/2 | foo

某些系统拒绝访问“/dev/stdout”,但用户终端允许访问“/dev/tty”。 使用"wc"代替"foo",上面的例子可以正常工作(在linux, OSX等)

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

要在匹配文件列表的底部添加一个计数,我使用如下代码 % ls [A-J]* | tee /dev/tty | wc -l < / p > 为了避免记住所有这些,我定义了别名:
% alias t tee /dev/tty < br > % alias wcl wc -l < / p >

,所以我可以简单地说:
% ls [A-J]* | t | wcl < / p >


后记:对于那些可能会因为“titty”的发音而窃笑的年轻人来说,我可以补充一点,“tty”曾经是很常见的 “电传打字机”终端的缩写,使用一卷黄色