如何在Windows批处理文件中有条件地打开/关闭@ECHO?

9
我有一个批处理文件,可以在本地或构建服务器上运行,用于执行某些有趣的任务。在本地机器上,我希望使用@ECHO OFF,以便控制台不会充满调试字符串。在构建服务器上,我更愿意使用@ECHO ON,以便可以调查失败情况。
如果存在一个特殊的环境变量(TEAMCITY_PROJECT_NAME),则可以确定构建服务器的上下文。因此,我认为可以这样做:
IF DEFINED TEAMCITY_PROJECT_NAME @ECHO ON ELSE @ECHO OFF

但是,这并没有起作用,我得到了IF语句和其他所有内容一起被打印出来...你有什么想法吗?


在本地运行它是一个频繁发生的情况吗?或者在本地运行会有什么“坏处”导致这些字符串? - Damien_The_Unbeliever
它并不经常运行,通常是我在测试更改,而且有输出也不算“糟糕”,但我希望它能够更加“性感”! - Anthony Mastrean
4个回答

16

该命令实际上并不叫做@echo@是一个可选标志,位于语句开头,表示对该语句进行了抑制。因此,在每个对echo命令的引用中使用@将隐藏echo命令本身,但不会隐藏它前面的if命令。

但实际导致您的命令无法按预期运行的问题是,第一个echo命令将吞掉该行上的其余标记作为其参数,因此else echo off部分将不会被CMD解释。由于CMD.EXE默认回显,因此它会打印if命令,然后执行单个echo命令或什么都不执行。由于@在作为if主体的语句开头具有意义,因此任何echo命令都不会被打印。

通常的解决方法是使用括号来界定命令边界。但由于默认情况下回显开启,您只需要在TEAMCITY_PROJECT未定义时才真正禁止回显,我们可以直接这样说。

@IF NOT DEFINED TEAMCITY_PROJECT_NAME ECHO OFF

为了抑制这一行的回显,我在开头留下了一个@,因此这一行不会出现在您服务器的日志中。

相关说明

回显状态也适用于交互式会话。在交互式CMD会话提示符处键入echo off将使其停止显示提示符。如果没有预期,这可能有点令人不安。键入echo on将恢复正常行为。

更多关于解析的内容

(我编辑了早期部分以提高其清晰度,并添加了该部分以尝试记录实际发生的事情。)

解释 .BAT 和 .CMD 脚本并在现代 Windows 提供交互式命令提示符的 CMD.EXE 程序非常好地记录了文档,但实际上却没有记录。我搜索官方文件以解释at-sign具有此效果以及可以使用它的确切位置的尝试基本不成功。

通过实验可以清楚地看到,如果@符号出现在命令的第一个非空字符处,则会对其进行解析和解释。我尝试通过上面的“语句开头”短语来表达这一点。

据我所知,CMD 的语言没有发表正式的语法。但是,从 CDM 本身的文档(在提示符处键入cmd /?),以及if /?和其他“有趣”的内置命令的内置帮助文本中,我们知道CMD解析其源文本时遵循一定的规则。

命令的开始似乎在一行的开头,在条件if之后,在else之后或在开放括号(之后。一旦识别出at-sign,则它适用于该命令的(大多数)余额。

尝试使用以下批处理文件,并移动“@”符号,您很快就会感受到规则很难精确说明:

rem this remark will echo
@rem this one will not
@ rem neither will this
 @rem nor this one
@rem the if command (and else) will echo, but not either echo command
if exist q17241089.bat ( @ echo saw q17241089.bat ) else @ echo foo
if not exist q17241089.bat ( @ echo no q17241089.bat ) else @ echo bar
@ rem none of the following command is echoed
@ if exist q17241089.bat ( @ echo saw q17241089.bat ) else @ echo spam

在我的Win 7 Pro上运行时,我看到:

C...>
C...>q17241089.bat

C...>rem this remark will echo

C...>if exist q17241089.bat ()  else
saw q17241089.bat

C...>if not exist q17241089.bat ()  else
bar
saw q17241089.bat
C...>

就像批处理文件的大部分细节一样,你只要挖掘一下,就会发现隐藏着许多奥秘。


感谢您更详细地解释了 @ 符号。我读了文档,错误地将其解释为仅修改 ECHO 命令的修饰符。您是说它修改了整行命令的默认回显,对吗? - Anthony Mastrean
是的,您可以在BAT文件的任何语句前面加上@,该语句将不会被回显。我会更新我的答案并添加一些细节,这些细节是我在尝试查找文档时发现的(显然没有文档)。 - RBerteig

4

设置括号(参见文档...):

IF DEFINED TEAMCITY_PROJECT_NAME (@ECHO ON) ELSE @ECHO OFF

2

看起来ECHO默认是开启的,所以无论你测试哪个条件,都会得到IF语句的输出。你应该从以下内容开始:

@ECHO OFF

将您的条件作为另一条语句进行评估并添加

@ECHO OFF && IF DEFINED TEAMCITY_PROJECT_NAME @ECHO ON

2

正如之前的回复所述,ECHO默认是开启的。实现相同行为的另一种方法是:

@if "%TEAMCITY_PROJECT_NAME%" == "" @echo off

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