2016-01-18 1 views
6

@echo onおよび@echo offは、バッチファイルの括弧で囲まれたifブロック内で実行された場合、影響を与えていないようです。ここでは簡単なデモです:バッチファイルのIFブロック内で@ECHOのON/OFFが機能しないのはなぜですか?

@echo off 
echo Test #1 
if 1 == 1 (
    @echo on 
    echo Test #2 
    @echo off 
    echo Test #3 
) 
@echo on 
echo Test #4 

コマンドライン上で上記を実行しているからの出力は次のとおりです。

テスト#1
テスト#2
テスト#3
C:\ mybatchfilelocation>エコーテスト#4
テスト#4

誰でもこれと/ oを説明できますかrは回避策を提案しますか? (それはおそらく豊富gotoの使用及びラベルによって固定することができますが、可能であれば場合は括弧で囲まれたブロックを引き続き使用することを好むだろうと期待しており...)

+0

現在の「エコーオン/オフ」状態は、行全体またはブロックのみに影響するためです。コマンドごとに個別に制御したい場合は 'echo on'を設定し、隠すコマンドの前に' @ 'を付けてください。 – aschipfl

+0

ありがとうございますが、残念ながら 'echo on'はカッコ内のコマンドをエコーし​​ません。 –

+0

私は理解していません、あなたの答えに 'echo'はどちらも 'echo'edです。それを隠すために 'echo'の前に '@'を置きます。 '' 'の前に' @ 'を入れて' if'の後ろのすべてを隠す... – aschipfl

答えて

5

あなたが発見したとして、それはECHO ON/OFFを含むコードブロックの後にある文を達するまで、変更ECHO状態はパーサによって認識されません。

しかし、1つの例外があります - FORの後のコマンド

ECHOが現在オンのときにコマンド出力を抑制するには、@が必要であることに注意してください。オフの場合、@ECHO ONの必要はありません。同じコードブロック内でONとOFFを切り替えると、そのコードブロックは必要ありません。 OUTPUT - - あなたはそれが便利なシンプルecho_on "マクロ" を宣言するかもしれません

Test #1 

C:\test>echo Test #2 
Test #2 
Test #3 

C:\test>echo Test #4 
Test #4 
Test #5 

C:\test>echo Test #6 
Test #6 
Test #7 

@echo off 
echo Test #1 
(
    echo on 
    for %%. in (.) do echo Test #2 
    echo off 
    echo Test #3 
    echo on 
    for %%. in (.) do echo Test #4 
    echo off 
    echo Test #5 
) 
echo on 
echo Test #6 
@echo off 
echo Test #7 

:ここ

も、テストラインをエコー表示のデモです。次の例は全く同じ出力を生成します:

@echo off 
setlocal 

set "echo_on=echo on&for %%. in (.) do" 

echo Test #1 
(
    %echo_on% echo Test #2 
    echo off 
    echo Test #3 
    %echo_on% echo Test #4 
    echo off 
    echo Test #5 
) 
echo on 
echo Test #6 
@echo off 
echo Test #7 
+0

偉大な答えと素敵なトリック!ただ一つのことですが、内部について何か知っていますか?つまり、なぜ 'FOR' ...' DO'がルールの例外なのですか? –

+1

@SteveChambers - FORが唯一のECHOコマンドです。 FOR文全体の最初のECHOは抑制されます。しかし、DOコマンドはその後、繰り返しごとに1回ECHOされます。詳細については、http://stackoverflow.com/a/4095133/1012053を参照してください。 – dbenham

1

は直前にエコーを回すことによって、これを引き起こしているものを見つけましたifブロック。

@echo on 
if 1 == 1 (
    echo Test #1 
    echo Test #2 
) 

この出力:

C:\ mybatchfilelocation>もし1 == 1(
エコー試験#1
エコーテスト#2

試験#1
試験#2

したがって、echブロック内の各ステートメントではなく、ブロックの場合は全体がです。 This answerはこれをさらに説明し、this answerは回避策を提供します - 残念ながら私が聞きたかったものではありませんが、それはgotoとラベルが唯一の実行可能な解決策であるかもしれません。

+1

私の経験では、カッコで「ブロック」を作成することは実際のプログラミング言語でそういったことをするのが本当に好きではありません。あなたがしている、私はあなたのように動作することを期待していただろうが、私はcmd/ifの奇妙な動作を参照して驚いていると言うことはできません。 – mojo

+1

この動作は、ブロック内で変更された変数にアクセスするために遅延拡張が必要な​​場合と同じです: 'echo on' _ブロックの前に 'echo off'を入れてもブロック内のすべての行が表示され、逆:ブロックの前に 'echo off'があると、ブロック内に' echo on'があってもすべての行が表示されません。最後のエコー状態は、ブロックの後の最初の行で使用されます。 – Aacini

2

あなたが望む結果を達成するために、このような何かを行うことができます:サブルーチン内のエコー制御コマンドを置くことについてどのように

@echo off 
set "ExecuteCmd=echo Test #2" 
echo Test #1 
if 1 == 1 (
    echo %ExecuteCmd% 
    %ExecuteCmd% 
    echo Test #3 
) 
@echo on 
echo Test #4 
+0

代わりに悪い試みはしませんが、 'if'ブロック内で実行可能なコマンドがたくさんあるので、' goto'sのように見え、ラベルはもっと実用的になるでしょう。 –

1

を?

@echo off 
echo Test #1 
if 1 == 1 (
    CALL :DO_ECHO_ON 
    echo Test #3 
) 
@echo on 
echo Test #4 

@EXIT /B 

:DO_ECHO_ON 
@ECHO ON 
echo Test #2 
@ECHO OFF 
@EXIT /B 

これは、私があなたの説明から期待する出力を生成します。

Test #1 

C:\secret>echo Test #2 
Test #2 
Test #3 

C:\secret>echo Test #4 
Test #4 

あなたのコメントの1つに基づいて、任意のコマンドに対してエコーを有効にしたいと思うと思います。この変更されたバージョンはそれを行います。

@echo off 
echo Test #1 
if 1 == 1 (
    CALL :DO_ECHO_ON_CMD echo Test #2 
    echo Test #3 
    CALL :DO_ECHO_ON_CMD dir /b "C:\Program Files" 
    echo Test #3.1 
    CALL :DO_ECHO_ON_CMD attrib c:\Windows 
) 
@echo on 
echo Test #4 

EXIT /B 

:DO_ECHO_ON_CMD 
@ECHO ON 
%* 
@ECHO OFF 
@EXIT /B 0 
関連する問題