禁止命令行输出

我有这样一个简单的batch file:

回声

 taskkill / im“test.exe”/ f> nul

暂停

如果“test.exe”没有运行,我得到这个消息:

错误:未find进程“test.exe”。

为什么会显示此错误消息,即使我已将输出redirect到NUL?

我怎样才能压制这个输出?

由于错误消息通常会转到stderr而不是stdout

将调用更改为:

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

一切都会好起来的

这是有效的,因为stdout是文件描述符1, stderr是文件描述符2。 (顺便说一句,0是stdin 。) 2>&1从刚刚被redirect到空设备的新值2>&1复制输出文件描述符2。

这个语法(松散地)从许多Unix shell中借用,但是你必须小心,因为shell语法和CMD.EXE之间有细微的差别。

更新:我知道OP了解NUL写在这里的“文件”的特殊性质,但一个评论者没有,所以让我在这方面稍微详细一点。

回到MSDOS最早的版本,某些文件名被文件系统内核抢占并用于引用设备。 最早的名单包括NULPRNCONAUXCOM1COM4NUL是空设备。 它可以随时打开,无论是阅读还是书写,任何数量都可以写在上面,读取总是成功的,但不返回任何数据。 其他包括并行打印机端口,控制台和最多四个串行端口。 从MSDOS 5开始,还有更多的保留名称,但是基本惯例已经很完善了。

当Windows被创build时,它开始在MSDOS内核之上作为相当薄的应用程序切换层,因此具有相同的文件名限制。 当Windows NT被创build为一个真正的操作系统的时候,像NULCOM1这样的名字被广泛地假定为可以消除。 然而,新设备总是会得到阻止这些名称用于实际文件的用户的想法显然是不合理的。

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

有关Windows中文件(和设备)合法名称的规则的完整说明, MSDN中的这个页面将是信息量大而令人生畏的。 这些规则比他们应该的要复杂得多,实际上不可能回答一些简单的问题,比如“最长的合法path名称最长是多less”。

改用这个脚本:

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

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

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

杀死任务“test.exe”。 将stderrredirect到stdout 。 然后,将stdoutredirect到nul

@暂停

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

注: @符号隐藏每个命令的提示。 这样可以保存多达8个字节。

您的脚本的最短版本可能是:
@taskkill/f /im test.exe >nul 2>&1&pause
&字符第一次用于redirect,第二次用于分隔命令。
一个@字符不需要在一行两次。 这个代码只有40个字节,尽pipe你已经发布了49个字节! 我实际上保存了9个字节。 上面的代码看起来更干净。

你也可以这样做:

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

mysqldump不能用于: > nul 2>&1
而是使用: 2> nul
这抑制了stderr消息:“警告:在命令行界面上使用密码可能是不安全的”