有趣的问题:-)
CMD 处理从左到右的重定向。您想首先将 2 (stderr) 重定向到 &1 (stdout),然后将 1 (stdout) 重定向到其他东西。此时stderr仍将被重定向到之前的stdout定义。管道仍然可以使用标准输出的旧定义(现在包含标准错误)。
如果你不关心标准输出,那么你可以重定向到 nul
program.exe 2>&1 1>nul | find " "
如果您想将标准输出捕获到文件然后重定向到文件
program.exe 2>&1 1>yourFile | find " "
如果您仍想在控制台上看到 stdout,但您只想将 stderr 传送到 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中。
所以从技术上讲,交换stderr和stdout不需要3的显式重定向
program.exe 2>&1 1>&3 | find " "
2>&1 将 stderr 保存在 3 中,并将 2 重定向到 &1 (stdout)。 1>&3 将 stdout 保存在 4 中,并且 1 被重定向到 &3 (stderr)。
但只有在您确定在发出命令之前尚未定义 3 时,上述操作才能正常工作。在我之前的代码示例中明确定义 3 会更安全。
请参阅Why doesn't my stderr redirection end after command finishes? And how do I fix it?,了解一些非常疯狂的重定向冒险:-)