33

我在 WindowsCMD.EXE环境中工作,并希望更改 的输出stdout以匹配的输出,stderr这样我就可以在没有文件中介的情况下将错误消息传递给其他程序。

我知道这个2>&1符号,但它结合stdoutstderr成为一个单一的流。

我在想的是这样的:

program.exe 2>&1 | find " "

但这结合了 stdout 和 stderr 就像:

program.exe | find " " 2>&1

我意识到我可以做...

program 2>file
type file | find " "
del file

但这不具备program | find " "某种符号的灵活性和力量。这样做需要program在可以处理该输出之前完成其输出。

4

2 回答 2

48

有趣的问题:-)

CMD 处理从左到右的重定向。您想首先将 2 (stderr) 重定向到 &1 (stdout),然后将 1 (stdout) 重定向到其他东西。此时stderr仍将被重定向到之前的stdout定义。管道仍然可以使用标准输出的旧定义(现在包含标准错误)。

如果您不关心标准输出,那么您可以重定向到 nul

program.exe 2>&1 1>nul | find " "


如果要将标准输出捕获到文件,然后重定向到文件

program.exe 2>&1 1>yourFile | find " "


如果您仍想在控制台上看到标准输出,但您只想通过管道将标准错误传送到 FIND,那么您可以将 1 重定向到 con:

program.exe 2>&1 1>con: | find " "

请注意,stdout 和 con: 的原始定义之间存在细微差别。例如,cls >con:不清除屏幕,而是在屏幕上打印一个有趣的字符。

如果您使用第三个(最初未使用的)文件句柄,则可以真正交换 stdout 和 stderr。1 和 3 将包含 stderr 的原始定义,2 将包含 stdout 的原始定义。

program.exe 3>&2 2>&1 1>&3 | find " "

实际上,每次执行重定向时都会定义一个额外的文件句柄。原始定义保存在第一个可用的未使用文件句柄中。假设在发出上述命令之前没有任何重定向。3>&2不保存 3 的原始定义,因为 3 之前没有定义。但是2>&1将stderr的原始定义保存在4中(3已经用过),1>&2将stdout的原始定义保存在5中。

所以从技术上讲,不需要 3 的显式重定向来交换 stderr 和 stdout

program.exe 2>&1 1>&3 | find " "

2>&1将 stderr 保存在 3 中,并将 2 重定向到 &1(stdout)。1>&3将标准输出保存在 4 和 1 被重定向到 &3 (stderr)。

但是,只有在您确定在发出命令之前尚未定义 3 时,上述操作才能正常工作。在我之前的代码示例中明确定义 3 会更安全。

请参阅为什么我的 stderr 重定向在命令完成后没有结束?我该如何解决?对于一些非常疯狂的重定向冒险:-)

于 2012-09-05T03:34:09.257 回答
3

从查看http://support.microsoft.com/kb/110930看来您想要2>&1 1>NUL. 因此,以下内容应该适合您:

test.exe 2>&1 1>NUL | find "someErrorString"
于 2012-09-05T03:34:37.420 回答