有没有办法将仅标准错误输出重定向到标准输出(而不是合并两者),以便可以将其导入其他程序?
有没有办法将仅标准错误输出重定向到标准输出(而不是合并两者),以便可以将其导入其他程序?
我在Windows的CMD.EXE
环境中工作,想要将stdout
的输出与stderr
的输出保持一致,这样我就可以将错误消息直接传输给其他程序,而不需要通过文件中转。
我知道2>&1
的表示方法,但它会将stdout
和stderr
合并为一个流。
我想的是这样的:
program.exe 2>&1 | find " "
但这样做会像下面这样将stdout和stderr合并:
program.exe | find " " 2>&1
我意识到我可以这样做...
program 2>file type file | find " " del file
但这样做没有program | find " "
这种表示法的灵活性和强大功能。这样做要求在处理输出之前program
已经完成了输出。
在CMD中,重定向的处理是从左到右的。首先,将2(stderr)重定向到&1(stdout),然后将1(stdout)重定向到其他地方。此时,stderr仍然会被重定向到stdout的前一个定义中。管道仍然可以使用旧的stdout的定义(现在包含stderr)。
如果不关心stdout,可以将其重定向到nul:
program.exe 2>&1 1>nul | find " "
如果想要将stdout捕获到文件中,则将其重定向到文件:
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中。
因此,从技术上讲,不需要显式重定向3来交换stderr和stdout:
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?。
- 添加了另一种比使用con更可靠的选项:
但是对我来说,3>&2 2>&1 1>&3
和2>&1 1>&3
都会将stdout和stderr合并。
- 真的吗?对我来说,在Vista和Windows 7上都可以正常工作。我还没有机会在XP上检查。DIR DoesNotExist 2>&1 1>&3 | FIND ""
将空目录列表传递到屏幕,但会删除错误消息,而DIR DoesNotExist 2>&1 1>&3 | FIND /V ""
同时传递空目录列表和错误消息。
DIR DoesNotExist 2>&1 1>&3 | FIND ""
会删除错误消息,而... | find " "
会显示两者。我原以为DIR DoesNotExist 2>&1 1>&3
和DIR DoesNotExist 2>&1 1>&3 | find " "
是相同的,因为DIR DoesNotExist 2>&1 1>nul
可以工作。此外,我不确定为什么stderr
等于""
,所以我不明白... | find ""
是如何工作的(我使用的是Windows 7 Ultimate x64)。
- 我认为你的问题可能是你的测试有问题。... | FIND " "
将匹配任何包含空格的行。... | FIND /V ""
是FIND的一个怪癖,它匹配所有行,我从未理解为什么,但它很有用。... | FIND ""
不会匹配任何行。我选择这些形式是为了验证stderr是否被传递而stdout不被传递。
奇怪。现在我对重定向的工作原理更加了解了,再次感谢!