exec n<&m 与 exec n>&m —— 基于 Sobell 的 Linux 书籍

发布于 2024-11-05 02:51:34 字数 531 浏览 4 评论 0 原文

在 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

复制标准输出吗?

In Mark Sobell's A Practical Guide to Linux Commands, Editors, and Shell Programming, Second Edition he writes (p. 432):

The <& token duplicates an input file
descriptor; >& duplicates an output
file descriptor.

This seems to be inconsistent with another statement on the same page:

Use the following format to open or
redirect file descriptor n as a
duplicate of file descriptor m:

exec n<&m

and with an example also on the same page:

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

If >& duplicates an output file descriptor then should we not say

exec 4>&1

to duplicate standard output?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

安人多梦 2024-11-12 02:51:34

这个例子在实践中是正确的。这本书的原始解释是对 POSIX 标准内容的准确描述,但是我手头有类似 POSIX 的 shell(bashdash,我认为唯一常见的 shell 是Linux 上看到的)并不那么挑剔。

POSIX 标准 关于输入和操作的说法与本书相同输出描述符,并继续这样说:对于 n<&word,“如果 word 中的数字不代表已打开用于输入的文件描述符,则重定向将导致错误”。所以如果你想注意 POSIX 兼容性,你应该避免这种用法。

bash 文档还< 也说了同样的事情 ;&>&,但不会出现错误。这很好,因为它实际上不会给出错误。相反,根据经验,n<&mn>&m 似乎是可以互换的。 <&>& 之间的唯一区别是,如果您省略左侧的 fd 编号,<& > 默认为 0 (stdin),>& 为 1 (stdout)。

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

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

它确实有效,并且这适用于 shell 使用 dashbash (或 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 and dash, 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 in word 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, empirically n<&m and n>&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 the exec 4<&1 example, try to write to the resulting fd 4, and see if it works:

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

It does, and this holds using either dash or bash (or bash --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.]

人│生佛魔见 2024-11-12 02:51:34

如果 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

我得到以下输出(在终端上键入“Reading from”行上 : 之后的内容):

$ ./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

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:

#!/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

I get the following output (the stuff after the : on "Reading from" lines is typed at the terminal):

$ ./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
魂牵梦绕锁你心扉 2024-11-12 02:51:34

请注意文件描述符和 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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文