取消命令行输出

我有一个这样的简单批处理文件:

echo off


taskkill /im "test.exe" /f > nul


pause

如果“ test.exe”没有运行,我会得到以下消息:

ERROR: The process "test.exe" not found.

即使我已经将输出重定向到 NUL,为什么还会显示这个错误消息?

如何抑制该输出?

194962 次浏览

因为错误消息经常发送到 stderr而不是 stdout

将调用更改为:

taskkill /im "test.exe" /f >nul 2>&1

一切都会好起来的。

这是因为按照惯例,stdout是文件描述符1,而 stderr是文件描述符2。(顺便说一句,0是 stdin。)2>&1将输出文件描述符2从新值1中复制出来,这个值刚刚被重定向到 null 设备。

这种语法(松散地)借用了许多 Unix shell,但是您必须小心,因为 shell 语法和 CMDEXE 之间存在细微的差异。

更新: 我知道 OP 理解我在这里写的名为 NUL的“文件”的特殊性质,但是一个评论者没有理解,所以让我离开这个方面的更多细节。

回溯到最早的 MSDOS 版本,某些文件名被文件系统内核抢占,用于引用设备。最早的名单包括 NULPRNCONAUXCOM1COM4NUL是空设备。它总是可以打开以进行读或写操作,任何数量都可以写在上面,读操作总是成功,但不返回数据。其他的包括并行打印机端口、控制台和最多四个串行端口。在 MSDOS 5中,还有几个保留的名称,但是基本约定已经很好地建立起来了。

在创建 Windows 时,它最初是作为 MSDOS 内核之上的一个相当薄的应用程序切换层,因此具有相同的文件名限制。当 Windows NT 作为一个真正的操作系统被创建的时候,像 NULCOM1这样的名字被广泛的认为是不允许它们被消除的。然而,认为新设备总是会获得名称来阻止未来用户将这些名称用于实际文件的想法显然是不合理的。

Windows NT 以及随后的所有版本(2K、 XP、7和现在的8)都使用了来自内核代码的更为复杂的 NT 命名空间,并使用了精心构造的高度不可移植的用户空间代码。在该名称空间中,设备驱动程序通过 \Device文件夹可见。为了支持所需的向下兼容,有一个使用 \DosDevices文件夹的特殊机制,该文件夹实现了任何文件系统文件夹中的保留文件名列表。用户代码可以使用通常的 Win32 API 之下的 API 层来查看这个内部名称空间; 来自 Microsoft 的 SysInternals 组的 WinObj是一个探索内核名称空间的好工具。

对于 Windows 中文件(和设备)的合法名称规则的完整描述,在 MSDN 的这个页面将是信息丰富和令人生畏的。规则是 很多,比它们应该的更复杂,而且实际上不可能回答一些简单的问题,例如“最长的合法完全限定路径名是多长?”.

你也可以这样做:

tasklist | find /I "test.exe" > nul && taskkill /f /im test.exe > nul

Mysqldump 不能使用: > 无效2 > 及1
而是使用: < b > 2 > null
这将禁止显示 stderr 消息: “警告: 在命令行接口上使用密码可能是不安全的”

使用以下脚本:

@taskkill/f /im test.exe >nul 2>&1
@pause

2>&1部分实际做的是将 stderr输出重定向到 stdout。我将在下面更好地解释:

@ taskkill/f/im test.exe > null 2 > & 1

终止任务“ test.exe”。将 stderr重定向到 stdout。然后,将 stdout重定向到 nul

@ 暂停

显示暂停消息 Press any key to continue . . . ,直到有人按下一个键。

注意: @符号隐藏了每个命令的提示符。这样最多可以节省8个字节。

你的剧本最短的版本可以是:
@taskkill/f /im test.exe >nul 2>&1&pause
&字符第一次用于重定向,第二次用于分隔命令。
一行中不需要两次 @字符。这段代码只有40个字节,尽管您发布的代码是49个字节!实际上我节省了9个字节。对于更干净的代码,请看上面。