问题描述
我在 Windows CMD.EXE
环境中工作,想更改 stdout
的输出以匹配 stderr
的输出,所以我可以在没有文件中介的情况下将错误消息传递给其他程序.
我知道 2>&1
表示法,但是它将 stdout
和 stderr
组合成一个流.>
我的想法是这样的:
program.exe 2>&1 |寻找 " "
但这结合了 stdout 和 stderr 就像:
program.exe |找到" 2>&1
我意识到我可以做到...
程序2>文件类型文件 |寻找 " "删除文件
但这不具备程序的灵活性和功能|找到"
种符号.这样做需要 program
在可以处理输出之前完成其输出.
有趣的问题 :-)
CMD 处理从左到右的重定向.您想首先将 2 (stderr) 重定向到 &1 (stdout),然后将 1 (stdout) 重定向到其他内容.此时stderr 仍会被重定向到stdout 的先前定义.管道仍将使用 stdout 的旧定义(现在包含 stderr).
如果你不关心 stdout 那么你可以重定向到 nul
program.exe 2>&1 1>nul |寻找 " "
如果要将标准输出捕获到文件,则重定向到文件
program.exe 2>&1 1>yourFile |寻找 " "
如果你仍然想在控制台上看到stdout,但你只想把stderr通过管道传送到FIND,那么你可以将1重定向到con:
program.exe 2>&1 1>con: |寻找 " "
请注意,stdout 和 con: 的原始定义之间存在细微差别.例如,cls >con:
不会清除屏幕,而是在屏幕上打印一个有趣的字符.
如果您使用第三个(最初未使用的)文件句柄,则可以真正交换 stdout 和 stderr.1 和 3 将包含 stderr 的原始定义,2 将包含 stdout 的原始定义.
program.exe 3>&2 2>&1 1>&3 |寻找 " "
实际上每次执行重定向时都会定义一个额外的文件句柄.原始定义保存在第一个可用的未使用文件句柄中.假设在发出上述命令之前没有任何重定向.3>&2
不保存 3 的原始定义,因为 3 之前没有定义.但是2>&1
在4中保存了stderr的原始定义(3已经用过了),而1>&2
在5中保存了stdout的原始定义.
因此从技术上讲,交换 stderr 和 stdout 不需要显式重定向 3
program.exe 2>&1 1>&3 |寻找 " "
2>&1
将 stderr 保存在 3 中,并且 2 被重定向到 &1 (stdout).1>&3
将 stdout 保存在 4 中,1 被重定向到 &3 (stderr).
但只有在您确定在发出命令之前尚未定义 3 时,上述内容才能正常工作.在我之前的代码示例中明确定义 3 更安全.
参见 为什么不命令完成后我的 stderr 重定向不是结束了吗?以及如何解决它? 用于重定向的一些非常疯狂的冒险:-)
I'm working in a Windows CMD.EXE
environment and would like to change the output of stdout
to match that of stderr
so that I can pipe error messages to other programs without the intermediary of a file.
I'm aware of the 2>&1
notation, but that combines stdout
and stderr
into a single stream.
What I'm thinking of would be something like this:
program.exe 2>&1 | find " "
But that combines stdout and stderr just like:
program.exe | find " " 2>&1
I realize that I could do...
program 2>file
type file | find " "
del file
But this does not have the flexibility and power of a program | find " "
sort of notation. Doing this requires that program
has finished with its output before that output can be processed.
Interesting question :-)
CMD processes redirection from left to right. You want to first redirect 2 (stderr) to &1 (stdout), then redirect 1 (stdout) to something else. At this point stderr will still be redirected to the previous definition of stdout. The pipe will still work with the old definition of stdout (which now contains stderr).
If you don't care about stdout then you can redirect to nul
program.exe 2>&1 1>nul | find " "
If you want to capture stdout to a file then redirect to a file
program.exe 2>&1 1>yourFile | find " "
If you still want to see stdout on the console, but you only want to pipe stderr to FIND, then you can redirect 1 to con:
program.exe 2>&1 1>con: | find " "
Note that there is a subtle difference between the original definition of stdout and con:. For example, cls >con:
does not clear the screen, it prints a funny character to the screen instead.
It is possible to truly swap stdout and stderr if you use a 3rd (initially unused) file handle. 1 and 3 will contain original definition of stderr, and 2 will contain original definition of stdout.
program.exe 3>&2 2>&1 1>&3 | find " "
Actually there is an additional file handle defined every time a redirection is performed. The original definition is saved in the first available unused file handle. Assume there has not been any redirection prior to issuing the above command. 3>&2
does not save the original definition of 3 because 3 was not previously defined. But 2>&1
saves the original definition of stderr in 4 (3 has already been used), and 1>&2
saves the original definition of stdout in 5.
So technically, the explicit redirection of 3 is not needed to swap stderr and stdout
program.exe 2>&1 1>&3 | find " "
2>&1
saves stderr in 3 and 2 is redirected to &1 (stdout). 1>&3
saves stdout in 4 and 1 is redirected to &3 (stderr).
But the above will only work properly if you are positive that 3 has not already been defined prior to issuing the command. It is much safer to explicitly define 3 as in my prior code example.
See Why doesn't my stderr redirection end after command finishes? And how do I fix it? for some really wild adventures with redirection :-)
这篇关于有没有办法只将 stderr 重定向到 stdout(而不是将两者结合起来),以便它可以通过管道传输到其他程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!