我想管道程序的标准输出,同时将其保留在屏幕上。
用一个简单的例子(echo
这里使用只是为了说明目的):
$ echo 'ee' | foo
ee
<- 我想看到的输出
我知道 tee 可以将标准输出复制到文件,但这不是我想要的。
$ echo 'ee' | tee output.txt | foo
我试过
$ echo 'ee' | tee /dev/stdout | foo
了,但它不起作用,因为 tee 输出通过/dev/stdout
管道传输到foo
这是一个适用于任何 Unix / Linux 实现的解决方案,假设它关心遵循POSIX
标准。它也适用于一些非 Unix 环境cygwin
。
echo 'ee' | tee /dev/tty | foo
参考: 开放组基本规范第 7 期 IEEE Std 1003.1,2013 版,§10.1:
/dev/tty
与该进程的进程组相关联(如果有)。无论输出如何重定向,它对于希望确保向终端写入消息或从终端读取数据的程序或 shell 过程很有用。它也可以用于要求输出文件名的应用程序,当需要键入输出并且查找当前正在使用的终端很烦人时。在每个进程中,控制终端的同义词
据报道,某些环境(例如 Google Colab)在/dev/tty
其tty
命令返回可用设备时并未实施。这是一种解决方法:
tty=$(tty)
echo 'ee' | tee $tty | foo
或使用古老的 Bourne 贝壳:
tty=`tty`
echo 'ee' | tee $tty | foo
另一件要尝试的事情是:
echo 'ee' | tee >(foo)
这>(foo)
是一个进程替换。
编辑:
为了更清楚一点,(。)在这里启动一个新的子进程到当前终端,输出被重定向到。
echo ee | tee >(wc | grep 1)
# ^^^^^^^^^^^^^^ => child process
除了子进程中的任何变量声明/更改不会反映在父进程中之外,在子进程中运行命令几乎没有问题。
尝试:
$ echo 'ee' | tee /dev/stderr | foo
当然,如果使用 stderr 是一种选择。
在某些系统上拒绝访问“/dev/stdout”,但访问用户终端是由“/dev/tty”提供的。对“foo”使用“wc”,上面的例子可以正常工作(在 linux、OSX 等上):
% echo 'Hi' | tee /dev/tty | wc Hi 1 1 3
要在匹配文件列表的底部添加计数,我使用如下内容:
% ls [A-J]* | tee /dev/tty | wc -l
为了避免记住所有这些,我定义了别名:
% alias t tee /dev/tty
% alias wcl wc -l
所以我可以简单地说:
% ls [A-J]* | t | wcl
后记:对于可能会嘲笑它的发音为“titty”的年轻群体,我可能会补充说,“tty”曾经是“电传打字机”终端的常见缩写,它使用一卷黄纸并有圆形键,通常卡住。
首先,您需要找出与您的屏幕关联的终端(或您希望输出显示的任何屏幕):
tty
然后您可以将输出发送到该终端并通过您的 foo 程序管道另一个副本:
echo ee | tee /dev/pty/2 | foo