Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I conditionally turn @ECHO ON/OFF in a Windows batch file?

I have a batch file that can be run locally or on the build server to do some kind of interesting job. On the local machine, I want @ECHO OFF so that your console isn't full of debug strings. On the build server, I'd rather have @ECHO ON so that failures can be investigated.

The build server context can be determined if a special environment variable exists (TEAMCITY_PROJECT_NAME). So, I thought I could do something like

IF DEFINED TEAMCITY_PROJECT_NAME @ECHO ON ELSE @ECHO OFF

But, that's not working, I get the IF statement echoed along with everything else... any thoughts?

like image 205
Anthony Mastrean Avatar asked Jun 21 '13 17:06

Anthony Mastrean


2 Answers

The command is not actually named @echo. The @ is an optional flag valid at the beginning of a statement to indicate that echo is suppressed for that statement. So using the @ on each reference to the echo command will hide the echo command itself, but not the if command that precedes it.

But the issue that is actually causing your command to fail to operated as expected is that the first echo command will slurp up the rest of the tokens on the line as its arguments, so the else echo off part will not be interpreted by CMD. Since CMD.EXE echoes by default it prints the if command, and then either executes a single echo command or nothing. Since the @ does have meaning at the start of the statement that is the body of the if, neither echo command would be printed.

In general, the solution to that is to use parenthesis to delimit the command boundaries. However, since echo is on by default and you really only want to suppress it if TEAMCITY_PROJECT is not define, we can say that directly.

@IF NOT DEFINED TEAMCITY_PROJECT_NAME ECHO OFF

I've left a single @ at the beginning to suppress echo of this line, and as a result this line will not appear in your server's logs.

Related note

The echo state also applies to an interactive session. Typing echo off at an interactive CMD session prompt will cause it to stop showing the prompt. Which is a tad disconcerting, if not expected. Typing echo on will restore normal behavior.

More on Parsing

(I've edited the earlier section for clarity, and added this section to attempt to document what is really happening.)

The CMD.EXE program that interprets .BAT and .CMD scripts, and provides the interactive command prompt in modern Windows is surprisingly well documented while effectively being undocumented. My attempts to search for an official document explaining that the at-sign has this effect and exactly where it can be used have been largely unsuccessful.

It is clear from experimentation that the at-sign is parsed and interpreted if it appears as the first non whitespace character of a command. I've tried to express that by using the phrase "beginning of a statement" above.

As far as I can tell there is no formal grammar published for CMD's language. But we do know from the documentation for CDM itself (type cmd /? to a prompt) as well as if /? and the built-in help text for other "interesting" built-in commands that there are rules that are followed when CMD parses its source text.

The start of a command appears to be at the beginning of a line, or after the conditional of an if, after the else, or after an open parenthesis (. Once the at-sign has been recognized, it applies to (most) of the balance of that command.

Try the following batch file yourself, and play with moving the at signs around and you'll quickly get the sense that the rules are hard to state precisely:

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

When run on my Win 7 Pro I see:

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...>

As with most of the fine details of BAT files, there is a mystery underneath any surface you scratch.

like image 62
RBerteig Avatar answered Oct 20 '22 19:10

RBerteig


set parentheses (see docu...):

IF DEFINED TEAMCITY_PROJECT_NAME (@ECHO ON) ELSE @ECHO OFF
like image 4
Endoro Avatar answered Oct 20 '22 21:10

Endoro