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?
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.
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.
(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.
set parentheses (see docu...):
IF DEFINED TEAMCITY_PROJECT_NAME (@ECHO ON) ELSE @ECHO OFF
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With