我还没有完全了解如何使用附加文件描述符。我怀疑您可以使用它们来模拟tee
实用程序的功能,查看命令的输出,同时将其写入文件。我还怀疑这样做会帮助我更好地理解如何使用附加文件描述符......
到目前为止我的尝试,
date 3>&1 3>file
我的想法是,创造3作为重复1(标准输出)和重定向3写入file
,因此我像往常一样将标准输出写入终端,并且3写入文件。
但这行不通。当我的时候cat file
,它是空的。我哪里做错了?
答案1
重定向运算符变化输出的去向(或输入的来源)。3>&1
意思是“让文件描述符3指向文件描述符1当前指向的任何地方”(即终端)。3>file
意思是“使文件描述符3指向file
”。在 fd 3 指向终端的短暂时间内没有发生任何事情,因此您不会得到任何终端输出。
为了在两个位置获取相同的数据,需要对数据进行复制。这是 的工作tee
。对于它读取的每个字节,它都会输出该字节两次(如果给定一个文件参数,加上其标准输出)。
>&
不要被有时称为重复的事实所困扰。它复制的是文件描述符:3>&1
将 fd 1 复制到 fd 3,这意味着发送到 fd 1 的数据和发送到 fd 3 的数据正在合并 — 它们都将发送到 fd 1 所指向的位置。
如果您喜欢图形解释,请参阅连接 STDOUT 和 STDIN 是什么意思?和一个命令如何可以有多个输出?
无论如何,您的命令不会在文件描述符 3 上输出任何内容,因此重定向 fd 3 不会改变任何内容。该date
命令写入其标准输出,即 fd 1,并且您没有重定向它。
Zsh 有一个功能叫做多操作系统这改变了输出重定向的含义。如果同一文件描述符上的同一命令有多个输出重定向,则第一个变化该描述符指向的位置,但后续的描述符复制将数据发送到指定的目标。例如,要获取文件中除了 stdout 指向的位置之外的输出,您可以使用
date >&1 >file
Zsh 正在做tee
.请注意,重定向的顺序很重要 - date >file >&1
将写入file
两次,因为在评估运算符时,>&1
标准输出date
已经是file
。
答案2
不,因为它不会重复输出。要复制文件描述符,您还必须向它们输出两次。
尽管您可以使用循环来完成此操作,如下所示:
while read l
do
echo "$l" >&3
echo "$l" >&4
done
对于二进制数据,它会出现错误(零被分块,crlf-s 将转换为 lf)。
你的例子是这样做的:
- 打开 fd 3 到文件
- 将 fd 1 克隆到代替 fd 3(即它关闭你以前的 fd3 ,然后使 fd3 成为你以前的标准输出的“替代地址”)。
重定向本质上是一个克隆,用unix术语来说,它就像一个硬链接。使用3>&1
命令后缀,您将拥有 fd 3 和 fd 1 指向同一实体(现在是file
)。
如果您对 C 有一定的兴趣,我想检查一下 a man 3 dup2
,这正是 fd 重定向的作用。