Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

restore the previous echo status

In a DOS Batch File subroutine, how can I turn off echo within the subroutine, but before returning, put it back to what it was before (either on or off)?

For example, if there was a command called echo restore, I would use it like this:

echo on
... do stuff with echoing ...
call :mySub
... continue to do stuff with echoing ...
exit /b

:mySub
@echo off
... do stuff with no echoing ...
echo restore
goto :EOF
like image 801
JoelFan Avatar asked Mar 06 '12 22:03

JoelFan


3 Answers

The simplest way is to not turn echo off in the first place.

Instead, do what you currently do with the echo off line to the rest of your subroutine - prefix all commands in the subroutine with an @ sign. This has the effect of turning off echo for that command, but keeps the echo state for future commands.

If you use commands that execute other commands, like IF or DO, you will also need to prefix the "subcommand" with an @ to keep them from being printed when echo is otherwise on.

like image 88
Michael Madsen Avatar answered Nov 20 '22 18:11

Michael Madsen


My first attempt was an utter failure - thanks jeb for pointing out the errors. For those that are interested, the original answer is available in the edit history.

Aacini has a good solution if you don't mind putting your subroutine in a separate file.

Here is a solution that works without the need of a 2nd batch file. And it actually works this time! :)

(Edit 2 - optimized code as per jeb's suggestion in comment)

:mysub
::Silently get the echo state and turn echo off
@(
  setlocal
  call :getEchoState echoState
  echo off
)
::Do whatever
set return=returnValue
::Restore the echo state, pass the return value across endlocal, and return
(
  endlocal
  echo %echoState%
  set return=%return%
  exit /b
)

:getEchoState echoStateVar
@setlocal
@set file=%time%
@set file="%temp%\getEchoState%file::=_%_%random%.tmp"
@(
  for %%A in (dummy) do rem
) >%file%
@for %%A in (%file%) do @(
  endlocal
  if %%~zA equ 0 (set %~1=OFF) else set %~1=ON
  del %file%
  exit /b
)

If you are willing to put up with the slight risk of two processes simultaneously trying to access the same file, the :getEchoState routine can be simplified without the need of SETLOCAL or a temp variable.

:getEchoState echoStateVar
@(
  for %%A in (dummy) do rem
) >"%temp%\getEchoState.tmp"
@for %%A in ("%temp%\getEchoState.tmp") do @(
  if %%~zA equ 0 (set %~1=OFF) else set %~1=ON
  del "%temp%\getEchoState.tmp"
  exit /b
)
like image 35
dbenham Avatar answered Nov 20 '22 18:11

dbenham


The easiest way is to extract the subroutine to another .bat file and call it via CMD /C instead of CALL this way:

echo on
... do stuff with echoing ...
cmd /C mySub
... continue to do stuff with echoing ...
exit /b

mySub.bat:

@echo off
... do stuff with no echoing ...
exit /b

This way the echo status will be automatically restored to the value it had when the CMD /C was executed; the only drawback of this method is a slightly slower execution...

like image 5
Aacini Avatar answered Nov 20 '22 20:11

Aacini