exec n<& m vs exec n>& m - 基于Sobell的Linux书籍

时间:2011-05-04 04:04:11

标签: linux bash shell unix file-descriptor

在Mark Sobell的 Linux命令,编辑和Shell编程实用指南,第二版中他写道(第432页):

  

<& token复制输入文件   描述; >&安培;复制输出   文件描述符。

这似乎与同一页面上的另一个陈述不一致:

  

使用以下格式打开或   将文件描述符n重定向为   复制文件描述符m:

     

exec n<& m

并在同一页上也有一个例子:

# File descriptor 3 duplicates standard input
# File descriptor 4 duplicates standard output
exec 3<&0 4<&1

如果&gt;&amp;复制输出文件描述符然后我们不应该说

exec 4>&1

复制标准输出?

3 个答案:

答案 0 :(得分:8)

这个例子在实践中是正确的。本书的原始解释是对POSIX标准所说内容的准确描述,但是我方便的(类似POSIX)shell(bashdash,我认为只有Linux上常见的那些)不是挑剔。

关于输入和输出描述符的POSIX标准says the same thing as the book,并继续这样说:对于n<&word,“如果word中的数字不代表已经打开的文件描述符输入,将导致重定向错误“。因此,如果你想要小心POSIX兼容性,你应该避免这种用法。

关于<&>&的bash文档也says the same thing,但没有错误的承诺。哪个好,因为它实际上没有给出错误。相反,凭经验n<&mn>&m似乎是可以互换的。 <&>&之间的唯一区别是,如果您忽略左侧的fd编号,<&默认为0(标准输入),>&默认为1(标准输出)

例如,让我们用fd 1指向文件bar启动一个shell,然后尝试完全exec 4<&1示例,尝试写入生成的fd 4,看看它是否有效:

$ sh -c 'exec 4<&1; echo foo >&4' >bar; cat bar
foo

确实如此,并且使用dashbash(或bash --posix)来保存shell。

引擎盖下,这是有道理的,因为&lt;&amp;和&amp;&amp;几乎可以肯定只是调用dup2(),它不关心fds是否可以读取或写入或追加或者是什么。

[编辑:在评论中讨论后添加了对POSIX的引用。]

答案 1 :(得分:2)

如果stdout是tty,则可以安全地克隆它以进行读取或写入。如果stdout是一个文件,那么它可能无法正常工作。我认为这个例子应该是4>&1。我同意Greg你可以读取和编写克隆描述符,但是请求使用<&重定向应该使用可读的源描述符来完成,并且期望stdout可读是没有意义的。 (虽然我承认我没有参考这个说法。)

一个例子可能会让它更清晰。使用此脚本:

#!/bin/bash

exec 3<&0
exec 4<&1

read -p "Reading from fd 3: " <&3
echo From fd 3: $REPLY >&2
REPLY=
read -p "Reading from fd 4: " <&4
echo From fd 4: $REPLY >&2

echo To fd 3 >&3
echo To fd 4 >&4

我得到以下输出(在“读取”行之后的东西在终端上输入):

$ ./5878384b.sh
Reading from fd 3: foo
From fd 3: foo
Reading from fd 4: bar
From fd 4: bar
To fd 3
To fd 4
$ ./5878384b.sh < /dev/null
From fd 3:
Reading from fd 4: foo
From fd 4: foo
./5878384b.sh: line 12: echo: write error: Bad file descriptor
To fd 4
$ ./5878384b.sh > /dev/null
Reading from fd 3: foo
From fd 3: foo
./5878384b.sh: line 9: read: read error: 0: Bad file descriptor
From fd 4:
To fd 3

答案 2 :(得分:0)

注意文件描述符和IO流之间的区别,例如stderr和stdout。

重定向运算符只是通过不同的文件描述符重定向IO流(IO流处理机制);他们不会复制或复制IO流(这就是tee(1)的用途)。

请参阅:File Descriptor 101

显示n&lt;&amp; m和n&gt;&amp; m可互换的另一个测试是“使用'n&lt;&amp; - '或'n&gt;&amp; - '两种方式来关闭文件描述符,即使它与使用“(http://www.gnu.org/s/hello/manual/autoconf/File-Descriptors.html)打开文件描述符的读/写模式不匹配。