1

Question

Is it possible to have a single-check toggle for the execution of multiple non-sequential lines in a batch file?

My Usage

Debug/trace lines that are distributed throughout the code.

Other Usages

I suppose this could be used in other ways, like enabling certain logic, but usually that would be better handled by flow of control.


I'm posting my own answer here that seems to work well. Feel free to share if you have other ideas.

u8it
  • 3,084
  • 1
  • 15
  • 28

2 Answers2

1

If you want to have toggleable lines of code, you can do something like this, example being a debug/trace implementation.

@Echo Off

::Set trace bit
set trace=0
::Optional: Prompt to enable
set /p trace=Trace is disabled. Enter 1 to enable: 

::Implement trace bit
if %trace% EQU 1 (
set trace=
) else (
set trace=@REM
) 

::Example Script (Lines that begin with %trace% are dependent on trace bit)
%trace% @Echo On
set x=5
%trace% @Echo Trace1: x=%x%
set /a y=5*%x%
%trace% @Echo Trace2: y=%y%
Echo On
set /a y=5*%y%
%trace% @Echo Trace3: y=%y%

pause

Explanation

This technique works by setting a parameter (%trace% in this example) to be a non-printing comment @REM if trace is off (= 0). This in effect masks your entire line of code by making it appear as a comment. If trace is enabled (= 1), then the %trace% variable is empty and the entire line of code executes as normal.

Line Masking Choice

The %Trace% variable could simply be REM, which will behave like @REM so long as you have Echo Off; however, if you have Echo On, it results in printed REM lines for the no trace option (trace = 0). For this reason, @REM is probably preferred.

enter image description here

Versus this...

enter image description here

Alternatives to @REM are <linefeed> or :: to mask the entire line and produce the following output even with Echo On and trace = 0; however, both of these options are problematic inside of bracketed code segments. The only benefit I can think of for them is that they might be faster, but that should be negligent.

<linefeed> is a non-obvious choice and works because the parser stops parsing and goes to the next line whenever it encounters a linefeed character. To set a variable equal to linefeed is a little tricky, but can be done as follows...

if %trace% EQU 1 (
set trace=
) else (
set trace=


) 
::The two new lines after "trace=" are required

See this answer as to why two lines are needed.

u8it
  • 3,084
  • 1
  • 15
  • 28
  • As you said `::` is problematic in parenthesis blocks, but `` fails completely in blocks, as it works like a command separator. `REM` is seems to be the best solution and even in `ECHO ON` mode it can safely used with `set "trace=@REM "` – jeb Feb 06 '18 at 12:13
  • @jeb I thought about the `` breaking in parentheses blocks too, but didn't test it; thanks for testing. Excellent point, `@REM` is probably the best overall solution. – u8it Feb 06 '18 at 13:54
1

I think, it's more obvious and more readable to use REM instead of the "linefeed trick"

@echo off
choice /c YN /m "enable debugging?"
if errorlevel 2 (set "debug=REM") else (set "debug=@")
::Example Script (Lines that begin with %debug% are dependent on debug bit)
%debug% @Echo On
set x=5
%debug% Echo debug1: x=%x%
set /a y=5*%x%
%debug% Echo debug2: y=%y%
set /a y=5*%y%
%debug% Echo debug3: y=%y%
echo last result: %y%
pause
Stephan
  • 47,723
  • 10
  • 50
  • 81
  • Ha, that's so obvious I feel silly for having posted with the linefeed method. I wonder if there's any functional difference? – u8it Feb 05 '18 at 20:50
  • Aw, there is a difference. If you have an `Echo On` section then the REM lines will still print. – u8it Feb 05 '18 at 21:42
  • 1
    might even be an advantage... `set "debug=@REM"` to suppress. – Stephan Feb 06 '18 at 06:11
  • yep, that's what jeb suggested too, `@REM` seems like the best solution. – u8it Feb 06 '18 at 14:00