276

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

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

$ echo 'ee' | foo
ee <- 我想看到的输出

我知道 tee 可以将标准输出复制到文件,但这不是我想要的。
$ echo 'ee' | tee output.txt | foo

我试过
$ echo 'ee' | tee /dev/stdout | foo了,但它不起作用,因为 tee 输出通过/dev/stdout管道传输到foo

4

5 回答 5

397

这是一个适用于任何 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/ttytty命令返回可用设备时并未实施。这是一种解决方法:

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

或使用古老的 Bourne 贝壳:

tty=`tty`
echo 'ee' | tee $tty | foo
于 2011-04-15T13:10:00.013 回答
77

另一件要尝试的事情是:

echo 'ee' | tee >(foo)

>(foo)是一个进程替换

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

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

除了子进程中的任何变量声明/更改不会反映在父进程中之外,在子进程中运行命令几乎没有问题。

于 2011-04-15T13:21:03.750 回答
21

尝试:

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

当然,如果使用 stderr 是一种选择。

于 2011-04-15T13:10:13.290 回答
20

在某些系统上拒绝访问“/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”曾经是“电传打字机”终端的常见缩写,它使用一卷黄纸并有圆形键,通常卡住。

于 2015-04-02T17:04:45.580 回答
12

首先,您需要找出与您的屏幕关联的终端(或您希望输出显示的任何屏幕):

tty

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

echo ee | tee /dev/pty/2 | foo
于 2013-08-02T20:04:06.180 回答