it-swarm.com.ru

Как условно включить/выключить @ECHO в командном файле Windows?

У меня есть командный файл, который можно запустить локально или на сервере сборки, чтобы сделать какую-то интересную работу. На локальном компьютере я хочу @ECHO OFF, чтобы ваша консоль не была полна строк отладки. На сервере сборки я предпочел бы иметь @ECHO ON, чтобы можно было исследовать ошибки.

Контекст сервера сборки можно определить, если существует специальная переменная среды (TEAMCITY_PROJECT_NAME). Итак, я думал, что мог бы сделать что-то вроде

IF DEFINED TEAMCITY_PROJECT_NAME @ECHO ON ELSE @ECHO OFF

Но, это не работает, я получаю эхом выражение IF вместе со всем остальным ... есть мысли?

9
Anthony Mastrean

На самом деле команда не называется @echo. @ является необязательным флагом, действительным в начале оператора, чтобы указать, что эхо подавлено для этого оператора. Таким образом, использование @ при каждой ссылке на команду echo скрывает саму команду echo, но не предшествующую ей команду if

Но проблема, которая фактически приводит к тому, что ваша команда не работает должным образом, заключается в том, что первая команда echo будет отбрасывать оставшиеся токены в строке в качестве своих аргументов, поэтому часть else echo off не будет интерпретироваться CMD. Поскольку CMD.EXE отображает эхо по умолчанию, он печатает команду if, а затем либо выполняет одну команду echo, либо ничего. Поскольку @ имеет значение в начале оператора, который является телом if, ни одна команда echo не будет напечатана.

Как правило, решение этой проблемы заключается в использовании скобок для разделения границ команд. Однако, поскольку echo включен по умолчанию, и вы действительно хотите подавить его, только если TEAMCITY_PROJECT не определен, мы можем сказать это напрямую.

@IF NOT DEFINED TEAMCITY_PROJECT_NAME ECHO OFF

Я оставил один @ в начале, чтобы подавить эхо этой строки, и в результате эта строка не будет отображаться в журналах вашего сервера.

Связанное примечание

Состояние эха также применяется к интерактивному сеансу. Ввод echo off в интерактивной подсказке сеанса CMD приведет к тому, что он перестанет отображать подсказку. Что немного смущает, если не ожидается. Ввод echo on восстановит нормальное поведение.

Подробнее о разборе

(Я отредактировал предыдущий раздел для ясности и добавил этот раздел, чтобы попытаться задокументировать, что на самом деле происходит.)

Программа CMD.EXE, которая интерпретирует сценарии .BAT и .CMD и предоставляет интерактивную команду Prompt в современной Windows, на удивление хорошо документирована, но при этом фактически не имеет документов. Мои попытки найти официальный документ, объясняющий, что знак «at» имеет этот эффект и где именно его можно использовать, в значительной степени не увенчались успехом.

Из экспериментов ясно, что знак at анализируется и интерпретируется, если он появляется как первый непробельный символ команды. Я попытался выразить это, используя фразу «начало утверждения» выше. 

Насколько я могу судить, не существует формальной грамматики для языка CMD. Но мы знаем из документации для самого CDM (типа cmd /? для подсказки), а также if /? и встроенного текста справки для других «интересных» встроенных команд, что существуют правила, которые соблюдаются, когда CMD анализирует свой исходный текст ,.

Начало команды, по-видимому, начинается в начале строки или после условия if, после else или после открытой скобки (. После того, как знак at был распознан, он применяется к (большей части) баланса этой команды.

Попробуйте сами следующий пакетный файл и поиграйте с перемещением знаков «в», и вы быстро поймете, что правила сложно точно сформулировать:

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

Как и в случае с большинством мелких деталей файлов BAT, под любой поверхностью, которую вы царапаете, есть загадка.

15
RBerteig

установить скобки (см. документ ...):

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

Похоже, что ECHO включен по умолчанию, так что вы получите вывод оператора IF, когда будете проверять это условие. Вы должны начать с

@ECHO OFF

И добавьте свое условное выражение как другое утверждение для оценки

@ECHO OFF && IF DEFINED TEAMCITY_PROJECT_NAME @ECHO ON
2
Anthony Mastrean

Как отмечалось в предыдущих ответах, ECHO включено по умолчанию. Альтернативный способ достижения того же поведения:

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