cmd.exe重定向运算符的顺序和位置

3

首先是关于顺序

以下方法可以将stdoutstrerr重定向到nul

command 1>nul 2>&1

以下内容不会:
command 2>&1 1>nul

为什么顺序很重要?这些表达式如何用通俗易懂的语言阅读?
关于位置
这个可以工作。
command 1>nul 2>&1

还有这个

1>nul 2>&1 command

为什么?有任何官方的语法规则参考文档会很有帮助。

2个回答

9

command 2>&1 1>nul 不起作用是不正确的。它可以工作。但通常情况下,它只会做你要求的事情,而不是你想要的。

从左到右:

  • 2>&1 将数据发送到流2(stderr),并将其发送到流1(stdout)使用的副本/复制品

  • 1>nul 将数据发送到流1,并将其发送到nul

副本是关键。数据不会被发送到流1指向的任何内容,而是发送到流句柄的副本。当流1被重定向时,流2有自己的句柄,一个先前流1的副本。更改流1不会影响流2。

现在,让我们看看工作代码,从左到右:

  • 1>nul 将流1中的句柄设置为指向nul

  • 2>&1 将流2中的句柄设置为流1中正在使用的句柄的副本,即指向nul的句柄

关于位置

大多数时候,位置(命令前、命令后或两者)都不重要。要执行命令,解析器必须首先准备命令将使用的流。在开始命令执行之前,如果认为有必要(尝试重定向rem命令输入或输出),会进行此准备。

唯一区别的情况是我们想从命令获取的内容和解析器理解的内容不相同的情况。一个明显的例子是当我们需要输出带有结尾数字的字符串时的代码。

echo 1 2 3>file 

不会将完整字符串发送到目标文件。 1 2 将被输出到控制台,并且写入流3的数据(此命令中没有内容)将被发送到file
当然,可以在数据末尾添加空格(在 3> 之间),但是该空格将包含在输出中。如果不接受这种情况,则解决方案是将重定向放在命令开头。
>file echo 1 2 3

绝对清晰的解释,我一直在使用1>nul 2>&1来抑制输出,甚至没有理解它,可能是因为我从未找到更好的解释。但是,位置呢? - Jaime Hablutzel
@JaimeHablutzel,抱歉,我忘记了问题的这一部分。现在已经包含在内了。 - MC ND

1

CMD简单地模拟了MSDOS 5中的command.com。添加的额外功能被应用为一个"shell",封装现有功能和怪癖,以确保现有批处理文件受到的影响最小。

开发人员做出了许多难以理解的决定。这似乎是一个低优先级的监督不力的项目,证据是内置文档中拼写错误和不一致性,选择将前导零字符串解释为八进制而不是十进制,并且没有使用类似于十六进制的H'123'O'123'。日期/时间工具中没有通用日期格式的/u开关,以及数十个其他需要解决的怪癖 - 这些都表明这是一个监督不力的项目,交给了一个对商业编程的现实没有经验的鲁莽开发者。

因此,2&1语法是一个附加功能,被糟糕地应用于一个希望在点、击和傻笑的一代的压力下消失的产品上。因此,它并不是"工业强度"的 - 然而具有讽刺意味的是,它已经存活了这么长时间。

过去十年或更长时间里,它的“穷亲戚”地位表明它几乎没有得到进一步的发展。由于它不够华丽,而且向后兼容,因此在其中没有赚钱的机会,这些根本上是扎根于20世纪50年代的思维方式。
因此,商业上没有理由解决由DOS5之后的改进引入的异常情况。序列问题是由于程序员的心态而出现的,他们没有考虑到任何人会以与那个特定程序员认为合乎逻辑的方式以外的方式使用新设施。
因此,你要按照那个程序员决定的方式使用重定向,除非你能想出几百万来资助你想要的开发,否则很快就没有希望改变了。

1
Um 2>&1 来自UNIX,所以如果你认为这是一个难以理解的决定,你可以向Ken Thompson提出。 - Raymond Chen
4
下次有人抱怨"为什么微软要发明一种非标准的做事方式?",我会记住这个。 - Raymond Chen
@RaymondChen,UNIX在正式规范中有这种排序要求吗? - Jaime Hablutzel
2
@JaimeHablutzel 参考 Kernighan 和 Pike 的《UNIX 编程环境》。维基百科的文章也有解释。2>&1 >file 将错误信息发送到标准输出并将输出发送到文件。>file 2>&1 将错误和输出都发送到文件中。就像在编程语言中一样,顺序很重要,x = y; y = 2;y = 2; x = y; 是不同的。 - Raymond Chen
@sorontar:我使用H'123'作为汇编语句。奇怪的是,Winbatch在set /a语句中使用0x前缀来表示十六进制字符串,但不使用0O来表示八进制,考虑到变量不能以数字开头,因此以0开头表示“有些不寻常”。使用ISO8601提供了一种通用的日期格式,不是通过指定显示格式来实现的,而是通过提供一种基础方式来表达日期,从而使得日期可以无歧义地表示——将其转换为/从任何其他基础或格式都是相对简单的编程任务。我认为没有“美国中心主义”的理由。 - Magoo
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接