禁止命令行输出


118

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

回声

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

暂停

如果“ test.exe”未运行,则会显示以下消息:

错误:找不到进程“ test.exe”。

即使我将输出重定向到NUL,为什么也会显示此错误消息?

如何抑制该输出?

Answers:


212

因为错误消息通常stderr不会stdout

将调用更改为此:

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

一切都会好起来的。

之所以有效,stdout是因为它是文件描述符1,并且stderr按照惯例是文件描述符2。(stdin顺便说一下,0是。)2>&1从新值1复制输出文件描述符2,该值刚刚重定向到空设备。

该语法是(宽松地)从许多Unix Shell中借用的,但是您必须要小心,因为Shell语法和CMD.EXE之间存在细微的差异。

更新:我知道OP知道NUL我在此处写的“文件”的特殊性质,但是评论者没有,所以让我在这方面做些更多的论述。

一直追溯到MSDOS的最早版本,某些文件名被文件系统内核抢占,并用于引用设备。这些名字的最早的名单包括NULPRNCONAUXCOM1通过COM4NUL是空设备。它始终可以打开以进行读取或写入,可以在上面写入任何数量,并且读取总是成功,但不返回任何数据。其他包括并行打印机端口,控制台和最多四个串行端口。从MSDOS 5开始,还有几个保留名称,但是基本约定非常明确。

创建Windows时,它是作为MSDOS内核之上的一个相当薄的应用程序交换层开始的,因此具有相同的文件名限制。当Windows NT本身被创建为真正的操作系统时,像NUL和这样的名称COM1都被广泛认为无法允许其删除。但是,新设备将始终获得会阻止将来使用这些名称的实际文件名称的想法显然是不合理的。

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

有关Windows中文件(和设备)合法名称的规则的完整说明,MSDN上的此页面将内容丰富,令人生畏。规则是一个很多比他们应该更加复杂,它实际上是不可能回答一些简单的问题,比如“有多长最长的法律完全合格的路径名?”。


5
感谢您的回答,最重要的是您的解释。
JosephStyons

的建议:taskkill /im "test.exe" /f >%temp%\nul 2>&1 & del %temp%\nul。这将防止将空白的空文件放置到本地目录中
Samy Bencherif 2013年

11
@SamyBencherif NUL是保留文件名,并且映射到NUL设备。您无法NUL在任何目录中创建实际名称的文件。
RBerteig

7

请改用以下脚本:

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

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

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

杀死任务“ test.exe”。重定向stderrstdout。然后,重定向stdoutnul

@暂停

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

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

脚本的最短版本可能是:
@taskkill/f /im test.exe >nul 2>&1&pause
&字符用于重定向的第一次,对分离命令的第二次。
一个@在一条线上,不需要两次字符。这段代码只有40个字节,尽管您张贴的是49个字节!我实际上保存了9个字节。有关更干净的代码,请参见上面。


是的,我知道一半的职位实际上是如何缩短您的代码。
EKons,2015年

3

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


0

您也可以这样做:

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

尽管问题的上下文是批处理脚本,但我发现在PowerShell中,以上语法失败,并带有“ out-file:要求FileStream打开不是文件的设备。以支持'com1:'或'lpt1这样的设备: ”,叫的CreateFile,然后使用该采取OS句柄作为一个IntPtr因此FileStream构造函数。 “的解决办法是更换> nul>$null
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.