我有一个简单的批处理文件,内容如下:
echo off
taskkill /im "test.exe" /f > nul pause
如果“test.exe”没有运行,则会显示以下错误信息:
ERROR: The process "test.exe" not found.
为什么即使我将输出重定向到nul,也会显示这个错误消息?
如何抑制此输出?
我有一个简单的批处理文件,内容如下:
echo off
taskkill /im "test.exe" /f > nul pause
如果“test.exe”没有运行,则会显示以下错误信息:
ERROR: The process "test.exe" not found.
为什么即使我将输出重定向到nul,也会显示这个错误消息?
如何抑制此输出?
stderr
而不是stdout
。将调用更改为以下内容:taskkill /im "test.exe" /f >nul 2>&1
这是可行的,因为按惯例,stdout
是文件描述符1,stderr
是文件描述符2。(0是stdin
)。 2>&1
将输出文件描述符2从刚刚重定向到空设备的1的新值中复制。
这种语法(宽松地)借鉴了许多Unix shell,但您必须小心,因为Shell语法与CMD.EXE之间存在细微的差异。
更新: 我知道OP理解我在此写入的名为NUL
的“文件”的特殊性质,但有评论者不明白,所以让我详细说明一下这个方面。
回到最早期的MSDOS版本,某些文件名被文件系统内核抢先使用并用于引用设备。最早的这些名称列表包括NUL
、PRN
、CON
、AUX
和COM1
到COM4
。NUL
是空设备,它可以始终打开进行读取或写入,可以在其上写入任意数量,读取始终成功但返回无数据。其他设备包括并口打印机端口、控制台和最多四个串行端口。自MSDOS 5以来,有几个保留名称,但基本约定已非常确立。
当Windows创建时,它作为在MSDOS内核之上的一个相对较薄的应用程序切换层开始运行,因此具有相同的文件名限制。当Windows NT被创建为真正独立的操作系统时,像NUL
和COM1
这样的名称被认为太广泛且适合工作,以允许它们被消除。但是,新设备总会得到将阻止将来使用这些名称的实际文件的名称的想法显然是不合理的。
Windows NT及其后续版本(2K、XP、7和现在的8)都使用更加详细复杂的NT名称空间,从内核代码到精心构造的高度不可移植的用户空间代码都遵循此规则。在该命名空间中,设备驱动程序可以通过\Device
文件夹进行访问。为了支持所需的向后兼容性,有一个特殊机制使用\DosDevices
文件夹,在任何文件系统文件夹中实现了保留文件名列表。用户代码可以使用Win32 API下面的API层浏览此内部名称空间;一个探索内核命名空间的好工具是微软SysInternals组的WinObj。
要了解有关Windows中文件(和设备)合法名称的规则的完整描述,请参阅MSDN此页面,这既有启发性又令人望而生畏。这些规则比本应如此的更加复杂,实际上无法回答一些简单的问题,例如“最长合法完全限定路径名是多少字符长?”。
@taskkill/f /im test.exe >nul 2>&1
@pause
2>&1
的作用是将stderr
输出重定向到stdout
。下面我会更好地解释它:
结束任务 "test.exe"。将stderr
重定向到stdout
。然后将stdout
重定向到nul
。
显示暂停消息按任意键继续. . .
,直到有人按下一个键。
注意:符号@
隐藏了每个命令的提示。这样可以节省多达8个字节。
你的脚本的最短版本可能是:
@taskkill/f /im test.exe >nul 2>&1&pause
第一次使用&
字符进行重定向,第二次用于分隔命令。
在一行中不需要两次使用@
字符。尽管你发布的代码长度为49字节,但这段代码只有40字节!我实际上节省了9个字节。请看上面更干净的代码。
使用>nul 2>&1无法正常运行mysqldump命令。
可以使用2> nul来代替,这样就可以屏蔽掉stderr信息:"Warning: Using a password on the command line interface can be insecure"。
你也可以这样做:
tasklist | find /I "test.exe" > nul && taskkill /f /im test.exe > nul
> nul
替换为 >$null
。 - weir
taskkill /im "test.exe" /f >%temp%\nul 2>&1 & del %temp%\nul
。这将防止一个空的 null 文件被放置到本地目录中。 - Samie BencherifFileStream was asked to open a device that was not a file. For support for devices like 'com1:' or | 'lpt1:', call CreateFile, then use the FileStream constructors that take an OS handle as an IntPtr.
- jjxtra