抑制命令行输出

Jos*_*ons 112 batch-file

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

echo off

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

pause

如果"test.exe"没有运行,我会收到以下消息:

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

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

如何抑制输出?

RBe*_*eig 201

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

将调用更改为:

taskkill /im "test.exe" /f >nul 2>&1
Run Code Online (Sandbox Code Playgroud)

一切都会好起来的.

这是因为stdout是文件描述符1,并且stderr按照惯例是文件描述符2.(0是stdin顺便说一句.)2>&1副本输出文件描述符2来自新值1,它刚被重定向到空设备.

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

更新:我知道OP理解NUL我在这里写的"文件"的特殊性,但是一个评论者却没有,所以让我在这个方面稍微详细一点.

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

创建Windows时,它在MSDOS内核之上作为一个相当薄的应用程序切换层开始生效,因此具有相同的文件名限制.当Windows NT本身作为一个真正的操作系统被创建时,类似的名称NULCOM1被广泛认为可以用来消除它们.然而,新设备总是会获得名称以阻止这些名称的实际文件的未来用户的想法显然是不合理的.

Windows NT和随后的所有版本(2K,XP,7和现在8)都遵循内核代码中更精细的NT命名空间,以及精心构建的高度非便携式用户空间代码.在该名称空间中,通过该\Device文件夹可以看到设备驱动程序.为了支持所需的向后兼容性,有一种特殊的机制,使用\DosDevices在任何文件系统文件夹中实现保留文件名列表的文件夹.用户代码可以使用通常的Win32 API下面的API层来浏览此内部名称空间; 一个探索内核命名空间的好工具是来自Microsoft的SysInternals组的WinObj.

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

  • @SamyBencherif,`NUL`是一个保留的文件名,并映射到NUL设备.您无法在任何目录中创建名为`NUL`的实际文件. (9认同)
  • 谢谢你的回答,最重要的是解释. (5认同)

小智 7

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


EKo*_*ons 7

请改用此脚本:

@taskkill/f /im test.exe >nul 2>&1
@pause
Run Code Online (Sandbox Code Playgroud)

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个字节.为了更清晰的代码看上面.