在 bash 中,您可以执行以下操作:
echo test >&1
(重定向到标准输出,虽然它已经在那里了)echo test >&2
(重定向到标准错误)echo test >&0
(重定向到标准输入)
当我做最后一个时,我的终端仍然test
像其他两个一样打印,但很难知道为什么。所以首先,为什么这会起作用?其次,重定向到标准输入有什么好的用途吗?
更准确地说,>&0
将文件描述符 0 复制为文件描述符 1。如果程序的 stdin 仅打开以供读取,那么当您的程序尝试写入 stdout(文件描述符 1)时,它会得到一个错误,因为文件描述符1也只开放阅读。
您可以通过编写一个检查其自己的文件描述符的小型 shell 脚本来证明这一点:
10156115.sh:
#!/bin/bash
bash -c 'ls -l /proc/$$/fd' >&0
然后用可识别的标准输入、标准输出和标准错误调用它:
$ touch stdin
$ ./10156115.sh < stdin > stdout 2> stderr
结果是您得到以下内容stderr
:
ls: write error: Bad file descriptor
但是,默认情况下,这三个都是终端:(输出简化)
$ ls -l /proc/$$/fd
lrwx------ 0 -> /dev/pts/14
lrwx------ 1 -> /dev/pts/14
lrwx------ 2 -> /dev/pts/14
lrwx------ 255 -> /dev/pts/14
通常,这三个实际上都是开放式读写的,因此>&0
如果在普通 shell 中单独使用重定向,则根本没有效果。
这有什么用途吗?
这没有任何常见用途,但是如果调用您的脚本的人重定向stdout
andstderr
并且无论出于何种原因您无法更改它,您可能会将其用作肮脏的黑客来获得一种打印到终端的方法:
if [ ! -t /dev/fd/1 -a ! -t /dev/fd/2 -a -t /dev/fd/0 ]; then
echo "My message that I really, really want to go to a terminal" >&0
fi
但我不建议实际这样做。
由于历史原因,终端上的标准文件描述符是打开读/写而不是只读的(具体来说,它打开一次并dup()
编辑给其他人)。这对于想要获取管道输入但也从用户(从stdout
,或更常见的stderr
)读取输入的程序来说有时很有用,尽管/dev/tty
在这种情况下使用更可靠。一些系统不仅将它应用于 ttys:*BSD 双向打开套接字对(“管道”),并且一些系统实用程序(我记得ufsdump
是一个例子)依赖于此。
重定向到 stdin
(即,只为写入而打开)通常没有用,因为大多数程序都希望它以读取方式打开(或有时读/写,如上所述)。