Почему @ECHO ON/OFF не работает в пакетном файле, если блок?

@echo on и @echo off Кажется, не влияет при выполнении в квадратных скобках if блок в пакетном файле. Вот простой пример:

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

вывод из выполнения вышеуказанного в командной строке:

4 ответов


как вы обнаружили, измененное состояние эха не распознается синтаксическим анализатором, пока он не достигнет оператора, который находится после блока кода, содержащего Эхо ВКЛ / ВЫКЛ.

но есть одно исключение - команды для ... DO do возьмите на себя изменение состояния в том же блоке : -)

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

вот демонстрация, которая повторяет четные тестовые строки:

@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

вы можете счесть удобным объявить простой echo_on "макрос". Следующее производит точно такой же вывод:

@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

только что выяснили, что вызывает это, включив Эхо до an if блок.

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

вот результаты:

C:\mybatchfilelocation>если 1 == 1 (
тест Эхо #1
тест Эхо #2
)
Тест № 1
Тест № 2

таким образом, утверждение, которое повторяется, является весь блок if а не каждое утверждение внутри него. ответ объясняет это дальше и ответ дает обходной путь - к сожалению не то, что я хотел услышать, но похоже, что много gotoS и метки могут быть единственным работоспособным решением.


вы можете сделать что-то подобное, чтобы достичь желаемого результата:

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

как насчет размещения команд управления эхом внутри подпрограммы?

@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

основываясь на одном из ваших комментариев, я полагаю, вы хотите включить echo для произвольных команд. Эта измененная версия делает это.

@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