我正面临一个无法解释的问题。我必须重新编码外壳程序,这对我来说是一种奇怪的行为。
echo test >&2 2>&1
这种命令是在stderr上编写的(因此使用第一个重定向),为什么第二个重定向不影响输出目标?为什么输出不在stdout上?
我看到一些东西在执行命令之前发生了重定向,从左到右,所以为什么第二个重定向没有取消第一个呢?
谢谢。
编辑:我正在bash上运行脚本。
答案 0 :(得分:2)
x>&y
的意思是“将文件描述符x重定向到当前 指向的。
重定向从左到右严格处理。
因此,>&2 2>&1
将fd 1指向/ dev / stderr之类的东西,然后还将fd 2指向/ dev / stderr。
如果要交换 stderr和stdout,则需要第三个文件描述符:
(echo "test to stdout"; echo "test to stderr" >&2) 3>&1 1>&2 2>&3 3>&-
# ................................................ A .. B .. C .. D
# A. fd 3 = /dev/stdout
# B. fd 1 = /dev/stderr
# C. fd 2 = /dev/stdout
# D. fd 3 is closed
让我们把它放在一个函数中,以便于测试
fdtest() { (echo "test to stdout"; echo "test to stderr" >&2) 3>&1 1>&2 2>&3 3>&-; }
运行
$ fdtest
test to stdout
test to stderr
丢弃标准错误(我们希望在标准输出上看到“ stderr”消息)。
$ fdtest 2>/dev/null
test to stderr
丢弃标准输出(我们希望在标准err上看到“ stdout”消息)。
$ fdtest 1>/dev/null
test to stdout
答案 1 :(得分:1)
cmd >&2 2>&1
与cmd 2>&1 >&2
非常不同,因为重定向以不同的顺序发生。假设从一个进程调用了该命令,该进程将fd 1附加到名为“ output”的文件,将fd 2附加到名为“ error”的文件。然后cmd >&2 2>&1
将cmd
的stdout重定向到名为error
的文件,然后将cmd
的stderr重定向到与fd 1连接的任何文件,即名为{{1 }}。但是error
将首先将fd 2重定向到“输出”,并将fd 1重定向到同一位置。换句话说,cmd 2>&1 >&2
将所有内容写入stderr,cmd >&2 2>&1
将所有内容写入stdout。