exec n<&m 与 exec n>&m —— 基于 Sobell 的 Linux 书籍
在 Mark Sobell 的《Linux 命令、编辑器和 Shell 编程实用指南,第二版》中,他写道(第 432 页):
<&令牌复制输入文件 描述符; >&重复输出 文件描述符。
这似乎与同一页面上的另一个声明不一致:
使用以下格式打开或 将文件描述符 n 重定向为 a 文件描述符 m 的重复:
执行n<&m
并在同一页上有一个示例:
# File descriptor 3 duplicates standard input
# File descriptor 4 duplicates standard output
exec 3<&0 4<&1
If >&复制输出文件描述符那么我们不应该说
exec 4>&1
复制标准输出吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这个例子在实践中是正确的。这本书的原始解释是对 POSIX 标准内容的准确描述,但是我手头有类似 POSIX 的 shell(
bash
和dash
,我认为唯一常见的 shell 是Linux 上看到的)并不那么挑剔。POSIX 标准 关于输入和操作的说法与本书相同输出描述符,并继续这样说:对于
n<&word
,“如果word
中的数字不代表已打开用于输入的文件描述符,则重定向将导致错误”。所以如果你想注意 POSIX 兼容性,你应该避免这种用法。bash 文档还对
< 也说了同样的事情
;&
和>&
,但不会出现错误。这很好,因为它实际上不会给出错误。相反,根据经验,n<&m
和n>&m
似乎是可以互换的。<&
和>&
之间的唯一区别是,如果您省略左侧的 fd 编号,<&
> 默认为 0 (stdin),>&
为 1 (stdout)。例如,让我们启动一个 shell,其中 fd 1 指向一个文件
bar
,然后尝试一下exec 4<&1
示例,尝试写入生成的 fd 4,看看它是否有效:它确实有效,并且这适用于 shell 使用
dash
或bash
(或bash --posix
) 。在幕后,这是有道理的,因为 <&和>&几乎可以肯定只是调用 dup2(),它不关心 fd 是否打开用于阅读或写作或附加或其他什么。
[编辑:在评论中讨论后添加了对 POSIX 的引用。]
The example is right in practice. The book's original explanation is an accurate description of what the POSIX standard says, but the POSIX-like shells I have handy (
bash
anddash
, the only ones I believe are commonly seen on Linux) are not that picky.The POSIX standard says the same thing as the book about input and output descriptors, and goes on to say this: for
n<&word
, "if the digits inword
do not represent a file descriptor already open for input, a redirection error shall result". So if you want to be careful about POSIX compatibility, you should avoid this usage.The bash documentation also says the same thing about
<&
and>&
, but without the promise of an error. Which is good, because it doesn't actually give an error. Instead, empiricallyn<&m
andn>&m
appear to be interchangeable. The only difference between<&
and>&
is that if you leave off the fd number on the left,<&
defaults to 0 (stdin) and>&
to 1 (stdout).For example, let's start a shell with fd 1 pointing at a file
bar
, then try out exactly theexec 4<&1
example, try to write to the resulting fd 4, and see if it works:It does, and this holds using either
dash
orbash
(orbash --posix
) for the shell.Under the hood, this makes sense because <& and >& are almost certainly just calling dup2(), which doesn't care whether the fds are opened for reading or writing or appending or what.
[EDIT: Added reference to POSIX after discussion in comments.]
如果 stdout 是 tty,则可以安全地克隆它以进行读取或写入。如果 stdout 是一个文件,那么它可能不起作用。我认为这个例子应该是
4>&1
。我同意 Greg 的观点,即您可以读取和写入克隆描述符,但是使用<&
请求重定向应该使用可读的源描述符来完成,并且期望 stdout 可读并不没有道理。 (尽管我承认我没有这个说法的参考资料。)举个例子可能会更清楚。使用此脚本:
我得到以下输出(在终端上键入“Reading from”行上 : 之后的内容):
If stdout is a tty, then it can safely be cloned for reading or writing. If stdout is a file, then it may not work. I think the example should be
4>&1
. I agree with Greg that you can both read and write the clone descriptor, but requesting a redirection with<&
is supposed to be done with source descriptors that are readable, and expecting stdout to be readable doesn't make sense. (Although I admit I don't have a reference for this claim.)An example may make it clearer. With this script:
I get the following output (the stuff after the : on "Reading from" lines is typed at the terminal):
请注意文件描述符和 IO 流(例如 stderr 和 stdout)之间的区别。
重定向操作符只是通过不同的文件描述符(IO流处理机制)重定向IO流;它们不会对 IO 流进行任何复制(这就是 tee(1) 的用途)。
请参阅:文件描述符 101
显示 n<&m 和 n>&m 可以互换的另一个测试是“使用任一样式'n<&-' 或 'n>&-' 用于关闭文件描述符,即使它与打开文件描述符的读/写模式不匹配”(http://www.gnu. org/s/hello/manual/autoconf/File-Descriptors.html)。
Mind the difference between file descriptors and IO streams such as stderr and stdout.
The redirecting operators are just redirecting IO streams via different file descriptors (IO stream handling mechanisms); they do not do any copying or duplicating of IO streams (that's what tee(1) is for).
See: File Descriptor 101
Another test to show that n<&m and n>&m are interchangeable would be "to use either style of 'n<&-' or 'n>&-' for closing a file descriptor, even if it doesn't match the read/write mode that the file descriptor was opened with" (http://www.gnu.org/s/hello/manual/autoconf/File-Descriptors.html).