Why does @ECHO ON / OFF not work in an IF block of a block?

@echo on and @echo off do not seem to affect execution in the if block in the batch file. Here is a simple demo:

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

The output from the above on the command line:

Test number 1
Test number 2
Test number 3
C: \ mybatchfilelocation> echo Test # 4
Test number 4

Can someone explain this and / or suggest a workaround? (Expect that it can probably be fixed by abundantly using goto and labels, but will prefer to continue using brackets if possible if ...)

+6
source share
4 answers

As you have discovered, the changed ECHO state is not recognized by the parser until it reaches the instruction that is located after the code block that contains ECHO ON / OFF.

But there is one exception - commands after FOR ... DO accept a state change inside the same block :-)

Note that you only need @ to suppress the output of the command when ECHO is currently on. If it is off then there is no need for @ECHO ON . And if you turn it on and off in the same block of code, then you don't need that either.

Here is a demo that shows even test lines:

 @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 

- OUTPUT -

 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 

You may find it convenient to declare a simple echo_on macro. The result is the same result:

 @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 
+5
source

You can do something similar to achieve the desired result:

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

Just found out what causes this by turning the echo to the if block.

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

It is output:

C: \ mybatchfilelocation> if 1 == 1 (
echo Test # 1
echo Test # 2
)
Test number 1
Test number 2

Thus, the expression that is reflected is the whole if block, and not every expression inside it. This answer explains this further and this answer gives a workaround - unfortunately, not what I wanted to hear, but it looks like a lot of goto and shortcuts may be the only workable solution.

+1
source

How to add echo control commands to a subroutine?

 @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 

This will give the result that I expect from your description.

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

Based on one of your comments, I assume that you want to enable echo for arbitrary commands. This modified version does this.

 @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 
+1
source

All Articles