web-dev-qa-db-ja.com

Windowsバッチファイルで@ECHOを条件付きでオン/オフにするにはどうすればよいですか?

ローカルまたはビルドサーバーで実行して、ある種の興味深い仕事を行うことができるバッチファイルがあります。ローカルマシンでは、@ECHO OFFを使用して、コンソールがデバッグ文字列でいっぱいにならないようにします。ビルドサーバーでは、失敗を調査できるように@ECHO ONを使用したいと思います。

ビルドサーバーコンテキストは、特別な環境変数(TEAMCITY_PROJECT_NAME)が存在するかどうかを判断できます。だから、私は次のようなことができると思いました

IF DEFINED TEAMCITY_PROJECT_NAME @ECHO ON ELSE @ECHO OFF

しかし、それは機能していません。IFステートメントが他のすべてと一緒にエコーされます...何か考えはありますか?

9

コマンドの名前は実際には@echoではありません。 @は、ステートメントの先頭で有効なオプションのフラグであり、そのステートメントでエコーが抑制されていることを示します。したがって、echoコマンドへの各参照で@を使用すると、echoコマンド自体は非表示になりますが、その前にあるifコマンドは非表示になりません。

しかし、実際にコマンドが期待どおりに動作しない原因となっている問題は、最初のechoコマンドが引数として行の残りのトークンを丸呑みするため、else echo off部分がCMDによって解釈されません。 CMD.EXEはデフォルトでエコーするため、ifコマンドを出力し、単一のechoコマンドを実行するか、何も実行しません。 @は、ifの本体であるステートメントの先頭で意味を持っているため、どちらのエコーコマンドも出力されません。

一般に、これに対する解決策は、括弧を使用してコマンド境界を区切ることです。ただし、エコーはデフォルトでオンになっており、TEAMCITY_PROJECTが定義されていない場合にのみエコーを抑制したいので、直接言うことができます。

@IF NOT DEFINED TEAMCITY_PROJECT_NAME ECHO OFF

この行のエコーを抑制するために、最初に@を1つ残しました。その結果、この行はサーバーのログに表示されません。

関連メモ

エコー状態はインタラクティブセッションにも適用されます。インタラクティブなCMDセッションプロンプトでecho offと入力すると、プロンプトの表示が停止します。予想外の場合、これは少し当惑させられます。 echo onと入力すると、通常の動作に戻ります。

構文解析の詳細

(わかりやすくするために前のセクションを編集し、実際に何が起こっているのかを文書化するためにこのセクションを追加しました。)

.BATおよび.CMDスクリプトを解釈し、最新のWindowsで対話型コマンドPromptを提供するCMD.EXEプログラムは、驚くほど十分に文書化されていますが、事実上文書化されていません。アットマークがこの効果を持ち、正確にどこで使用できるかを説明する公式文書を検索する私の試みは、ほとんど失敗しました。

アットマークがコマンドの最初の非空白文字として表示される場合、アットマークが解析および解釈されることは実験から明らかです。上記の「声明の冒頭」という言葉を使ってそれを表現しようとしました。

私の知る限り、CMDの言語用に公開された正式な文法はありません。ただし、CDM自体のドキュメント(プロンプトにcmd /?を入力)、およびif /?と、他の「興味深い」組み込みコマンドの組み込みヘルプテキストから、 CMDがソーステキストを解析するときに続きます。

コマンドの開始は、行の先頭、またはifの条件の後、elseの後、または開き括弧(の後のように見えます。アットマークが認識されると、そのコマンドの残りの(ほとんど)に適用されます。

次のバッチファイルを自分で試して、アットマークを動かしてみてください。ルールを正確に記述するのが難しいという感覚がすぐにわかります。

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

括弧を設定します(docu ...を参照):

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

以前の応答で述べたように、ECHOはデフォルトでオンになっています。同じ動作を実現する別の方法は次のとおりです。

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