如何使Windows批处理脚本完全静默?

72

这个问题被问了很多年,但是尽管我写了一些相当复杂的Windows脚本,我似乎无法弄清楚如何使它们真正静默。

以下是我当前脚本的一部分摘录:

@ECHO OFF
SET scriptDirectory=%~dp0
COPY %scriptDirectory%test.bat %scriptDirectory%test2.bat
FOR /F %%f IN ('dir /B "%scriptDirectory%*.noext"') DO (
del "%scriptDirectory%%%f"
)
ECHO

其结果是:

C:\Temp> test.bat
        1 file(s) copied.
File Not Found
Echo is off.

C:\Temp>

虽然“已复制1个文件”只是让人烦恼的提示,但“找不到文件”会让用户觉得出了问题(实际上没有问题——没有文件也是正常情况)。


1
如果您最终使用了与所给出的不同的解决方案,请添加您自己的答案并接受它。不要将解决方案添加到问题本身。 - Shadow The Spring Wizard
我实际上通过在if条件语句前缀中加入一个if条件语句,成功地删除了第二个“文件未找到”的输出:IF EXIST“%scriptDirectory%* .noext” FOR / F%%f IN('dir / B“%scriptDirectory%* .noext”')DO(...)。最初这并不起作用,因为我曾尝试使用IF <condition> DO()。 - Mike Sadler
我已经更改了标题以反映@bobstein-visibone的[在我看来相当严厉]评论。 - Mike Sadler
5个回答

122

要抑制输出,请使用重定向到 NUL

控制台命令使用两种输出:

  • 标准输出,或 stdout

  • 标准错误,或 stderr

在这两个输出中,stdout 更常被使用,无论是内部命令,如 copy,还是控制台实用程序(也称为外部命令),如 find 等,以及第三方控制台程序。

>NUL 抑制标准输出,例如,可以屏蔽 copy 命令的 1 file(s) copied. 消息。另一种语法是 1>NUL。因此,

COPY <i>file1</i> <i>file2</i> <b>>NUL</b>
或者
COPY <i>file1</i> <i>file2</i> <b>1>NUL</b>
或者
<b>>NUL</b> COPY <i>file1</i> <i>file2</i>
或者
<b>1>NUL</b> COPY <i>file1</i> <i>file2</i>

抑制所有COPY的标准输出。

要抑制通常打印到stderr的错误消息,请改用2>NUL。 因此,为了抑制DEL在找不到指定文件时打印的文件未找到消息,只需在命令行的开头或结尾添加2>NUL

DEL <i>file</i> <b>2>NUL</b>
或者
<b>2>NUL</b> DEL <i>file</i>

有时在尝试删除文件之前实际验证该文件是否存在可能是更好的选择,就像您在自己的解决方案中所做的那样。但请注意,您不需要使用循环逐个删除文件。您可以使用单个命令批量删除:

IF EXIST "%scriptDirectory%*.noext" DEL "%scriptDirectory%*.noext"

1
谢谢,@AndriyM - 我实际的脚本不仅仅是删除文件,但我为了问题而将其简化了。如果我使用 1>NUL,那么错误消息是否仍然会被显示?那将是一个改进。 - Mike Sadler
1
@MikeSadler:是的,1>NUL只会抑制标准输出。错误输出仍然会显示出来。当你需要抑制一个命令的所有输出时,同时使用1>NUL2>NUL - Andriy M
完美 - 如果有错误消息,我很乐意让用户看到。 - Mike Sadler
3
copy 命令在执行时不会将错误信息输出到 stderr,而是会输出到 stdout。使用 copy ... >nul 可以隐藏正常输出和错误信息。但 xcopy 命令可以正确地处理这些信息,所以可能是一个好的选择。(还可以设置 xcopy /q 选项来摆脱复制文件名的显示。) - ygoe
应该是 copy /y ... - Nam G VU

15

如果您希望批处理脚本的所有正常输出都保持静默(就像您的示例中一样),最简单的方法是使用重定向运行批处理文件:

C:\Temp> test.bat >nul

这种方法不需要修改脚本中的任何一行,仍然可以在屏幕上显示错误消息。如果要抑制所有输出,包括错误消息:

C:\Temp> test.bat >nul 2>&1

如果您的脚本有产生输出并想要在屏幕上显示的行,也许将重定向添加到那些行会更简单,而不是所有您想要保持静默的行:

@ECHO OFF
SET scriptDirectory=%~dp0
COPY %scriptDirectory%test.bat %scriptDirectory%test2.bat
FOR /F %%f IN ('dir /B "%scriptDirectory%*.noext"') DO (
del "%scriptDirectory%%%f"
)
ECHO
REM Next line DO appear in the screen
ECHO Script completed >con

安东尼奥


3
将名为html的目录及其所有内容复制到静默模式下的目标目录中。如果目标目录不存在,它仍将创建该目录。
@echo off
TITLE Copy Folder with Contents

set SOURCE=C:\labs
set DESTINATION=C:\Users\MyUser\Desktop\html

xcopy %SOURCE%\html\* %DESTINATION%\* /s /e /i /Y >NUL

  1. /S 复制目录和子目录,但不包括空目录。

  2. /E 复制目录和子目录,包括空目录。与 /S /E 相同。可用于修改 /T。

  3. /I 如果目标不存在且复制的是多个文件,则假定目标必须是一个目录。

  4. /Y 禁止提示确认是否要覆盖现有目标文件。

3
您可以将标准输出重定向到 nul 来隐藏它。
COPY %scriptDirectory%test.bat %scriptDirectory%test2.bat >nul

只需在要隐藏输出的命令后添加>nul

在这里你可以看到所有不同的重定向标准流的方式。


3

只需在生成消息的行末添加>NUL

例如,

COPY %scriptDirectory%test.bat %scriptDirectory%test2.bat >NUL


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接