在Windows中,无论是在命令行还是批处理文件中,命令DIR 2>NUL: 3>&2
(您可以用任何内容替换DIR
,即使不是文件或命令)也会产生所有错误然后失踪,除非你在每个命令后写2>CON:
。为什么CMD甚至这样做?如何在不启动新的CMD流程的情况下恢复正常? DIR 2>CON: 3>&2
仅适用于该命令。
编辑:这也适用于文件。 DIR 2>TEXT.TXT 3>&2
之后的任何错误都将附加到文件中。
答案 0 :(得分:30)
这是一个测试脚本,可以重现您遇到的问题。
@echo off
2>nul 3>nul (
echo I want to see stream1
1>&2 echo I don't want to see this stream2
1>&3 echo I don't want to see this stream3
)
echo stream1 works fine
1>&2 echo stream2 is now "permanently" void. I don't see this.
1>&3 echo stream3 works fine
这是输出
I want to see stream1
stream1 works fine
stream3 works fine
stderr(流2)已被“永久”禁用,即使对于父CMD.EXE shell也是如此。
您可以通过分阶段重定向来避免“永久”方面:
@echo off
2>nul (
3>nul (
echo I want to see stream1
1>&2 echo I don't want to see this stream2
1>&3 echo I don't want to see this stream3
)
)
echo stream1 works fine
1>&2 echo stream2 works fine
1>&3 echo stream3 works fine
这是所需的输出:
I want to see stream1
stream1 works fine
stream2 works fine
stream3 works fine
我真的不明白发生了什么。但我做了一些有趣的实验。看看这个主题:http://www.dostips.com/forum/viewtopic.php?f=3&t=2836&start=30
<强> 附录 强>
正如Erbert在他的评论中发现并分享的那样,如果你只是改变重定向的顺序,那么修复就更容易了 - 不需要进行修改。
@echo off
3>nul 2>nul (
echo I want to see stream1
1>&2 echo I don't want to see this stream2
1>&3 echo I don't want to see this stream3
)
echo stream1 works fine
1>&2 echo stream2 works fine
1>&3 echo stream3 works fine
更新2012-04-03 我相信我终于理解了Windows CMD.EXE重定向的机制。我有一个充分考虑所有奇怪行为的工作理论,包括为什么反转命令会阻止“永久”重定向。它还解释了Aacini的观察,即句柄3似乎与CON连接:(实际上,根据Windows文档,它实际上是未定义的)。
关键点是:
1 - 每当重定向句柄(流)时,原始定义将转移到第一个可用的未定义句柄。连续重定向总是从左到右进行。
2 - 重定向结束后,通常会恢复原始定义。但是如果存在一系列重定向,则恢复仅在1级深度进行。这是“永久”重定向的来源。
编辑2014-12-19:换句话说,恢复似乎是使用队列结构(FIFO - 先入先出)完成的,当它应该被实现为堆栈时( LIFO - 后进先出。)
3 - 当CMD.EXE执行重定向时,它首先将当前定义保存在未定义的句柄中,然后重定向第一个句柄。如果第一个句柄被重定向到最初未定义的句柄,那么它会被有效地重定向到其原始定义!这就是echo hello 1>&3
输出到控制台的原因。
完整的理论和测试用例可在http://www.dostips.com/forum/viewtopic.php?p=14612#p14612连续两个帖子中找到。
答案 1 :(得分:3)
我很抱歉将此作为答案而不是评论发布,但我的“评论”太大了......
在MS-DOS标准中,所有正在运行的程序都打开了这些标准句柄:0-STDIN(键盘),1-STDOUT(屏幕),2-STDERR(屏幕),3-STDAUX (串行端口)和4-STDPRN(打印机)。虽然Windows文档清楚地表明句柄3-9未定义,但句柄3由CMD.EXE进行特殊处理。我有三个理由认为这个:
1-手柄3连接到CON:设备(键盘用于输入,屏幕用于输出);句柄4-9不会:
C>ver
Microsoft Windows XP [Version 5.1.2600]
C>echo To handle 3 >&3
To handle 3
C>echo To handle 4 >&4
The handle could not be duplicated
during redirection of handle 1.
C>set /P var=From handle 3: <&3
From handle 3: Value entered in keyboard
C>echo %var%
Value entered in keyboard
C>set /P var=From handle 4: <&4
The handle could not be duplicated
during redirection of handle 0.
2-本主题中陈述的句柄3的奇怪行为,以两种不同的方式解决。我发现如果句柄0,1或2被重定向到句柄3(并且可能处理4-9),句柄0,1或2的重定向变为“永久”;如果句柄0,1或2是包含句柄3的重定向列表中的最后句柄,则不会发生此行为。如果句柄0,1或2,则完全避免此问题以任何顺序重定向手柄4-9,但不处理3。
3-使用TypeOfHandle.com program获得的结果。此程序是一个纯MS-DOS可执行文件,检查其参数中给出的句柄,如果句柄连接到CONsole设备,则通过errorlevel返回值3,如果句柄重定向到磁盘文件,则返回值128 。结果如下:
C>typeofhandle 0
C>echo %errorlevel%
3
C>typeofhandle 0 < anyFile.txt
C>echo %errorlevel%
128
C>typeofhandle 1
C>echo %errorlevel%
3
C>typeofhandle 1 > anyFile.txt
C>echo %errorlevel%
128
C>typeofhandle 3
C>echo %errorlevel%
0
C>typeofhandle 3 <&3 anyFile.txt
C>echo %errorlevel%
0
C>typeofhandle 3 >&3 anyFile.txt
C>echo %errorlevel%
0
句柄3-9在其他方面表现得很奇怪:
我的SetFilePointer.com program获得的结果。虽然可以在批处理文件中使用句柄3-9来实现一次输入/输出多个文件,但这种机制只允许顺序访问,因为我的SetFilePointer程序无法移动文件指针处理3-9。 SetFilePointer程序正确地处理句柄0,1和2;此功能允许批量编写完整的关系数据库应用程序。 this post
详细介绍了此主题答案 2 :(得分:0)
我认为答案可能只是使用句柄 5-7,您可以按照以下方式将它们分配给所需的文件来定义:
5>"%tmp%\MyFileX.txt"
6>"%tmp%\MyFileX.txt"
因此可以使用 1>&5
或 1>&6
重定向将输出定向到任一文件。
答案 3 :(得分:-2)
问题在于3>&2
。文件描述符3无效,它似乎以某种方式扰乱了Windows。把它关掉,你不需要它。
有关完整治疗,请参阅Microsoft's documentation (archived)。