I have written huge MS DOS Batch file. To test this batch file I need to execute some lines only and want to hide/comment out remaining.
I have some existing comment lines starting with :: hence I cannot use :: anymore as it will scramble all comments.
How can I solve this problem?
You can use a goto to skip over code.
goto comment
...skip this...
:comment
If you want to add REM at the beginning of each line instead of using GOTO, you can use Notepad++ to do this easily following these steps:
Select the block of lines
hit Ctrl-Q
Repeat steps to uncomment
break||(
code that cannot contain non paired closing bracket
)
While the goto solution is a good option it will not work within brackets (including FOR and IF commands).But this will. Though you should be careful about closing brackets and invalid syntax for FOR and IF commands because they will be parsed.
Update
The update in the dbenham's answer gave me some ideas.
First - there are two different cases where we can need multi line comments - in a bracket's context where GOTO cannot be used and outside it.
Inside brackets context we can use another brackets if there's a condition which prevents the code to be executed.Though the code thede will still be parsed
and some syntax errors will be detected (FOR,IF ,improperly closed brackets, wrong parameter expansion ..).So if it is possible it's better to use GOTO.
Though it is not possible to create a macro/variable used as a label - but is possible to use macros for bracket's comments.Still two tricks can be used make the GOTO
comments more symetrical and more pleasing (at least for me). For this I'll use two tricks - 1) you can put a single symbol in front of a label and goto will still able
to find it (I have no idea why is this.My guues it is searching for a drive). 2) you can put a single :
at the end of a variable name and a replacement/subtring feature will be not triggered (even under enabled extensions). Wich combined with the macros for brackets comments can
make the both cases to look almost the same.
So here are the examples (in the order I like them most):
With rectangular brackets:
#echo off
::GOTO comment macro
set "[:=goto :]%%"
::brackets comment macros
set "[=rem/||(" & set "]=)"
::testing
echo not commented 1
%[:%
multi
line
comment outside of brackets
%:]%
echo not commented 2
%[:%
second multi
line
comment outside of brackets
%:]%
::GOTO macro cannot be used inside for
for %%a in (first second) do (
echo first not commented line of the %%a execution
%[%
multi line
comment
%]%
echo second not commented line of the %%a execution
)
With curly brackets:
#echo off
::GOTO comment macro
set "{:=goto :}%%"
::brackets comment macros
set "{=rem/||(" & set "}=)"
::testing
echo not commented 1
%{:%
multi
line
comment outside of brackets
%:}%
echo not commented 2
%{:%
second multi
line
comment outside of brackets
%:}%
::GOTO macro cannot be used inside for loop
for %%a in (first second) do (
echo first not commented line of the %%a execution
%{%
multi line
comment
%}%
echo second not commented line of the %%a execution
)
With parentheses:
#echo off
::GOTO comment macro
set "(:=goto :)%%"
::brackets comment macros
set "(=rem/||(" & set ")=)"
::testing
echo not commented 1
%(:%
multi
line
comment outside of brackets
%:)%
echo not commented 2
%(:%
second multi
line
comment outside of brackets
%:)%
::GOTO macro cannot be used inside for loop
for %%a in (first second) do (
echo first not commented line of the %%a execution
%(%
multi line
comment
%)%
echo second not commented line of the %%a execution
)
Mixture between powershell and C styles (< cannot be used because the redirection is with higher prio.* cannot be used because of the %*) :
#echo off
::GOTO comment macro
set "/#:=goto :#/%%"
::brackets comment macros
set "/#=rem/||(" & set "#/=)"
::testing
echo not commented 1
%/#:%
multi
line
comment outside of brackets
%:#/%
echo not commented 2
%/#:%
second multi
line
comment outside of brackets
%:#/%
::GOTO macro cannot be used inside for loop
for %%a in (first second) do (
echo first not commented line of the %%a execution
%/#%
multi line
comment
%#/%
echo second not commented line of the %%a execution
)
To emphase that's a comment (thought it is not so short):
#echo off
::GOTO comment macro
set "REM{:=goto :}REM%%"
::brackets comment macros
set "REM{=rem/||(" & set "}REM=)"
::testing
echo not commented 1
%REM{:%
multi
line
comment outside of brackets
%:}REM%
echo not commented 2
%REM{:%
second multi
line
comment outside of brackets
%:}REM%
::GOTO macro cannot be used inside for
for %%a in (first second) do (
echo first not commented line of the %%a execution
%REM{%
multi line
comment
%}REM%
echo second not commented line of the %%a execution
)
Another option is to enclose the unwanted lines in an IF block that can never be true
if 1==0 (
...
)
Of course nothing within the if block will be executed, but it will be parsed. So you can't have any invalid syntax within. Also, the comment cannot contain ) unless it is escaped or quoted. For those reasons the accepted GOTO solution is more reliable. (The GOTO solution may also be faster)
Update 2017-09-19
Here is a cosmetic enhancement to pdub's GOTO solution. I define a simple environment variable "macro" that makes the GOTO comment syntax a bit better self documenting. Although it is generally recommended that :labels are unique within a batch script, it really is OK to embed multiple comments like this within the same batch script.
#echo off
setlocal
set "beginComment=goto :endComment"
%beginComment%
Multi-line comment 1
goes here
:endComment
echo This code executes
%beginComment%
Multi-line comment 2
goes here
:endComment
echo Done
Or you could use one of these variants of npocmaka's solution. The use of REM instead of BREAK makes the intent a bit clearer.
rem.||(
remarks
go here
)
rem^ ||(
The space after the caret
is critical
)
Just want to mention that pdub's GOTO solution is not fully correct in case :comment label appear in multiple times. I modify the code from this question as the example.
#ECHO OFF
SET FLAG=1
IF [%FLAG%]==[1] (
ECHO IN THE FIRST IF...
GOTO comment
ECHO "COMMENT PART 1"
:comment
ECHO HERE AT TD_NEXT IN THE FIRST BLOCK
)
IF [%FLAG%]==[1] (
ECHO IN THE SECOND IF...
GOTO comment
ECHO "COMMENT PART"
:comment
ECHO HERE AT TD_NEXT IN THE SECOND BLOCK
)
The output will be
IN THE FIRST IF...
HERE AT TD_NEXT IN THE SECOND BLOCK
The command ECHO HERE AT TD_NEXT IN THE FIRST BLOCK is skipped.
#jeb
And after using this, the stderr seems to be inaccessible
No, try this:
#echo off 2>Nul 3>Nul 4>Nul
ben ali
mubarak 2>&1
gadeffi
..next ?
echo hello Tunisia
pause
But why it works?
sorry, i answer the question in frensh:
( la redirection par 3> est spécial car elle persiste, on va l'utiliser pour capturer le flux des erreurs 2> est on va le transformer en un flux persistant à l'ade de 3> ceci va
nous permettre d'avoir une gestion des erreur pour tout notre environement de script..par la suite si on veux recuperer le flux 'stderr' il faut faire une autre redirection du handle 2> au handle 1> qui n'est autre que la console.. )
try this:
#echo off 2>Nul 3>Nul 4>Nul
ben ali
mubarak
gadeffi
..next ?
echo hello Tunisia
pause
Related
I'm trying to make a self-building chatbot that learn questions by inputing question and three possible answers, then, it randomize that three answers and give it as output. The learned question goes to the final line of the same batch file.
Here's the sample:
#echo off&&setlocal enabledelayedexpansion
echo/teach me a question to answer.
set/p q=
echo(>>%~f0
echo/:%q: =%>>%~f0
cls
echo/teach me three ways to answer it.
set/p a1=
set/p a2=
set/p a3=
echo/set a[0]=%a1%>>%~f0
echo/set a[1]=%a2%>>%~f0
echo/set a[2]=%a3%>>%~f0
echo/"set/a ax=%random% %%3&&set aa=!a[%ax%]!">>%~f0
echo/"echo %aa%">>%~f0
But I get the following:
:howareyou?
a[0]=good
a[1]=fine
a[2]=well
"set/a ax=24793 %3&&set aa="
"echo "
It's possible to get
set/a ax=%random% %%3&&set aa=!a[%ax%]!
echo %aa%
exactly as it is?
There are two problems in this code.
First of all, to answer your question:
How to echo exactly what I type in?
In batch, the answer is always more complicated than you think. In case of echo, quotes don't really change the way % and ! interpreted, but they are echoed as well, which is bad now.
Instead, escape % by duplicating, & by putting a ^, and ! by putting two ^s before it [ref]:
echo set/a ax=%%random%% %%%% 3^&^&set aa=^^!a[%%ax%%]^^! >>%~f0
echo echo %%aa%% >>%~f0
Now you can see, that everything's echoed correctly, but the echoed code still won't work.
Why?
The second problem is the &&: percent-variables (%var%) will be substituted before the evaluation of the line or the command group (commands enclosed by parentheses).
That is, since the set /a and set are on the same line, %ax%'s value will be substituted before set /a sets it. That could be avoided by using the power of the Delayed Expansion, and its !ax! syntax, but in this case, it isn't possible because it is accessed inside another variable access.
So, instead do what && would do otherwise:
set/a ax=%random% %% 3
if %errorlevel% GTR 0 set aa=^^!a[%%ax%%]^^!
Finally, you end up with something like:
echo set/a ax=%%random%% %%%% 3 >>%~f0
echo if %%errorlevel%% GTR 0 set aa=^^!a[%%ax%%]^^! >>%~f0
echo echo %%aa%% >>%~f0
Take a look Here for a functional example of escaping exclamation marks used in delayed variables for this type of situation.
#echo off & setlocal DisableDelayedExpansion
Set "/Ex=^!"
and to utilize:
Echo(Set "Answer=%/Ex%Answer[%%RandAnswer%%]%/Ex%">>Bot.bat
Highly recommend reading here to understand the way the command line is parsed and why this works.
relevant code looks like this:
cd /d %~dp0
if exist filename.txt (
echo %date% %time% *** text... >> filename2.txt
echo ==============================
echo === text....... ===
echo === text....... ===
echo === text....... (text...) ===
echo === text (text...
echo === text...).
:loop
set /p "varx= text: "
if "%varx%" neq "xxxx" goto loop
... more script...
)
Have searched high and low for solutions...
was pointed in direction of If statement groupings here:
https://www.petri.com/forums/forum/windows-scripting/general-scripting/57625-if-exists-file-was-unexpected-at-this-time - NO GO
was pointed in direction of problems with loops in If blocks, here:
(Windows batch) Goto within if block behaves very strangely - NO GO
Was pointed in direction of using #setlocal enabledelayedexpansion or #setlocal enableextensions (can't track down where) - NO GO
tried passing filename via set /p varfile="filename" and if exist %varfile% - NO GO
of course thought there were other parts of code causing error -- NO GO
The thing is that this WAS working for a long while...then I changed what I thought was some innocuous stuff and cannot figure out where the problem lies...
such an obscure problem to solve..ugh!
WELL...I am posting this as a Q & A...because I solved my own problem (took me a couple of days of trial and error to narrow down and fix the problem). I am hoping this will help some poor soul too and save them a lot of heartache, and a few hair strands...
The thing that got me thinking the most was the second bullet regarding poor handling of loops inside If statements...BUT that was not the real reason but something similar...
It turns out the problem was with the use of "(' and/or ')' on the ECHO lines...
I thought this was innocuous... I use brackets in ECHO lines in lots of places, and these lines were about 10-15 lines down from where the error message was being generated, so naturally I was not thinking that this was at all the source.
BUT it turns out that the interpreter clearly does not like the use of '(' or ')' even on ECHO lines if they are used within the If statement blocks. It must still treat them as special characters in that context...it clearly does not ignore them...
Solution:
Either taking the '(' and ')' out of those 3 lines above OR simply REM those lines out solved the problem and the error message went away...all is finally well...
BTW it is possible that the a similar thing may apply to FOR statements too (I vaguely recall reading something about FOR acting strangely too).
So food for thought.
The entire compound-statement from the if exist ... ( through to the closing parenthesis is a code block.
Within a code block, labels are not allowed, an un-escaped ) will terminate the block and any %var% is replaced by that variable's value when the block is encountered.
You need to call the :loop routine (easiest way)
if exist filename.txt (
echo %date% %time% *** text... >> filename2.txt
echo ==============================
echo === text....... ===
echo === text....... ===
echo === text....... (text...^) ===
echo === text (text...
echo === text...^).
call :loop
... more script...
)
... etc
goto :eof
:loop
set /p "varx= text: "
if "%varx%" neq "xxxx" goto loop
goto :eof
Note the goto :eof is defined to be "go to end-of-file" (The colon is required)
Note the call has a colon before the label - this indicates it's an internal routine - it resides in this batchfile
Note that each ) is now escaped by a ^ which makes ) an ordinary character, not a statement-terminator.
You've probably removed a redirector - any echo within the called procedure will be gathered into the redirected output - that is if you have
(
whatever...
)>filename
then any data echoed within the code block will be redirected to the file - including echoes within a called procedure. You can explicitly redirect an echo within such a block or procedure using echo to console>con for instance.
Encasing any sequence of lines in parentheses, making it a code block allows redirection of the echoed output from the block, so
(
echo this
echo that
)>filename
creates a new filename containing the sum of the echoes rather than having to append >>filename to each line. Obviously, >> in place of > will append to any existing file in the usual manner.
I found this program web.archive.org: http://baiyunmanor.com/blog/work/get-current-date-time-in-dos-batch-file/
::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:: This uses Windows Scripting Host to set variables
:: to the current date/time/day/day_number
:: for Win9x/ME/NT/W2K/XP etc
:: Thanks go to Todd Vargo for his scripting
::::::::::::::::::::::::::::::::::::::::::::::::::::::::
#echo off
set TmpFile=”%temp%.\tmp.vbs”
echo> %TmpFile% n=Now
echo>>%TmpFile% With WScript
echo>>%TmpFile% .Echo “set year=” + CStr(Year(n))
echo>>%TmpFile% .Echo “set yr=” + Right(Year(n),2)
...
cscript //nologo “%temp%.\tmp.vbs” > “%temp%.\tmp.bat”
call “%temp%.\tmp.bat”
...
echo date F [ddmmyy] [%day%%month%%yr%]
:: datetime.bat
But I don't know what does the line
:: datetime.bat
at the end mean?
:: is a label (inaccurately also known as comment label) can be, in practice, considered a comment just as REM is, because it is an "un-goto-able" label.
There are some differences between REM and ::, though. The main ones are:
With ECHO ON a REM line is shown but not a line commented with ::
A :: can execute a line end caret (that is, a ^ at the end of a line starting with :: makes the next line also a comment):
:: This is a comment^
echo but watch out because this line is a comment too
Labels and :: have a special logic and can cause problems in parentheses blocks - take care when using them inside ( ). Example:
for %%D in (hi) do (
echo Before...
:: My comment
:: Some other comment
echo After...
)
Outputs:
Before ...
The system cannot find the drive specified.
After...
A line that start in double colon represent an invalid label that is ignored by the command processor, so it may be used to insert a comment. For reasons that can't be traced, many people use :: to insert comments in Batch files, but you must be aware that there are several pitfalls in its use that are described in the link given in Koterpillar's answer. It seems that the first use of :: instead of REM command was with the purpose to speed up the execution of Batch files in slow machines (ie: floppy disks), but that reason is not a valid justification for the use of double colon since many years ago.
Any line that contain an invalid label will be ignored by the command processor and you may use practically any special character to generate an invalid label. For example:
#echo off
:~ This is a comment
:` This is a comment
:! This is a comment
:# This is a comment
:# This is a comment
:$ This is a comment
:% This is a comment
:^ This is a comment
:& This is a comment
:* This is a comment
:( This is a comment
:) This is a comment
:_ This is a comment
:- This is a comment
:+ This is a comment
:= This is a comment
:{ This is a comment
:} This is a comment
:[ This is a comment
:] This is a comment
:| This is a comment
:\ This is a comment
:: This is a comment
:; This is a comment
:" This is a comment
:' This is a comment
:< This is a comment
:> This is a comment
:, This is a comment
:. This is a comment
:? This is a comment
:/ This is a comment
echo OK
In other words: if you want to insert a comment and you want not to use REM command (although I can't think of any reason to do so), you have 32 possible character combinations to do so. Why you should use precisely this one: ::? Just because some old programs written 35 years ago did it?
A line starting with a colon is a label which you can jump to with goto:
goto end
:end
A line starting with a double colon is a label, except you can't, even accidentally, jump to it:
goto :end REM this doesn't work
::end
Thus, double colon is used to comment lines out.
Source: http://www.robvanderwoude.com/comments.php
As mentioned by acdcjunior Labels and :: have a special logic and can cause problems in parenthesis blocks
Here are couple of samples
Sample 1
IF 1==1 (
::
)
Output of sample 1
) was unexpected at this time.
Sample 2
IF 1==1 (
::
::
)
Output of sample 2
The system cannot find the drive specified.
The colon (:) is a label marker and can be used for got instructions.
Some people use : as a comment too so a double colon is simply a stylistic REM statement
If you use the traditional REM command to comment out a line in a DOS batch script then any output redirection in the comment is still done. For example, consider this script:
echo 1 > a.txt
rem echo 2 > b.txt
echo 3 > c.txt
This script will truncate b.txt even though the line appears to be "commented out".
Using an invalid label prefix like the double colon will disable any redirection.
In one of my scripts, I need to use variables that contain parenthesis inside IF statements, but either the string is missing a closing parenthesis or the script exits prematurely with * was unexpected at this time (not actually an asterisk), depending on the scenario.
Example
#echo off
SET path=%programFiles(x86)%
echo Perfect output: %path%
IF NOT "%path%" == "" (
REM Variable is defined
echo Broken output: %path%
)
pause >nul
Output
Perfect output: C:\Program Files (x86)
Broken output: C:\Program Files (x86
I think/know that this is because it thinks the closing parenthesis in C:\Program Files (x86) is the end of the IF statement and it exits before the echo is complete.
Is there a simple way to cirumvent this? Preferably without resorting to
single-line IF statements, as I need to run more than one line of code within them,
copious amounts of GOTOs, as it's not practical,
SETLOCAL EnableDelayedExpansion and using !path! instead of %path%, as I recall reading somewhere that that method doesn't work consistently across OSs.
If not, I'll happily accept the most reliable solution offered, whatever it is.
(The scenario isn't up for debate. This is just a refined, concentrated example of the problem. The structure needs to be like this, as it is in my actual script, for reasons I won't go into. It's besides the point and it'll just confuse things and distract from the actual issue.)
First off - you should never use the PATH variable for your own use. It is a reserved environment variable. Using it for your own purposes can break your scripts.
The simplest solution really is to use delayed expansion. As long as your platform uses CMD.EXE then you have access to delayed expansion.
But there is a relatively easy way to make it work without delayed expansion. You can use disappearing quotes. The quote exists at parse time as the name of a FOR variable while the command is parsed. It expands to nothing before execution time.
#echo off
SET mypath=%programFiles(x86)%
echo Perfect output: %mypath%
IF NOT "%mypath%" == "" (
REM Variable is defined
for %%^" in ("") do echo fixed output: %%~"%mypath%%%~"
)
pause >nul
EDIT - When to use delayed expansion: Response to comment
I generally only use delayed expansion when it is needed (or more precisely, when it is advantageous). That being said, I usually find it advantageous in some portion of my batch code.
Major Advantages
Inside a code block in order to see changes to a variable within the block
When dereferencing the name of a variable. If a variable name is passed in as a parameter, the value of the variable can be gotten via delayed expansion: echo !%1!
When using variables as arguments to search and replace or substring operations: echo !var:%search%=%replace%!, echo !var:%start%,%len%!.
Whenever I need to expand the value and not worry about special characters within it needing escaping or quoting: set "var=A&B" & echo !var!
There are other methods to do the above (except the last), but delayed expansion is the easiest, most efficient (fastest to execute), and most reliable option.
Major Disadvantage
Any FOR variable that contains ! in its value will be corrupted when it is expanded if delayed expansion is enabled. I frequently toggle delayed expansion on and off within a FOR loop to get around the problem.
It is not good for executing a "macro" (executing code contained within a variable value) because many important phases of command parsing take place prior to the delayed expansion. So many batch features are unavailable to "macros" that are executed via delayed expansion.
my suggestion is :
if (condition_TRUE) goto goodbye_parenthesis_BEGIN
goto goodbye_parenthesis_END ----- line when previous condition is FALSE ----
:goodbye_parenthesis_BEGIN ----- line when previous condition is TRUE ----
...
variable treatment
...
:goodbye_parenthesis_END
The ) from the resolved variable in your echo statement is prematurely closing the IF block.
Ordinarily, you could fix that by escaping the ) with ^), but you can't modify the environment variable to resolve to C:\Program Files (x86^).
You can prevent this issue by surrounding the variable with quotes.
As a simpler example:
> SET bad=a)b
> IF 1 == 1 ( ECHO %bad% )
b was unexpected at this time.
> IF 1 == 1 ( ECHO "%bad%" )
"a)b"
As others already pointed out, the unescaped and unquoted closing parenthesis ) unintentionally ends the parenthesised if block.
Besides escaping, quotation, delayed expansion and "disappearing quotes", there are the following further options:
Use a for meta-variable on the quoted value and remove the quotes by the ~-modifier:
#echo off
set "PATH=%ProgramFiles(x86)%"
echo Perfect output: %PATH%
if not "%PATH%" == "" (
rem Variable is defined
for %%P in ("%PATH%") do echo Unbroken output: %%~P
)
pause > nul
Use the call command to initiate another variable expansion phase, together with doubled (escaped) %-symbols:
#echo off
set "PATH=%ProgramFiles(x86)%"
echo Perfect output: %PATH%
if not "%PATH%" == "" (
rem Variable is defined
call echo Unbroken output: %%PATH%%
)
pause > nul
Do escaping by sub-string substitution, which happens before ^-escaping is detected:
#echo off
set "PATH=%ProgramFiles(x86)%"
echo Perfect output: %PATH%
if not "%PATH%" == "" (
rem Variable is defined
echo Unbroken output: %PATH:)=^)%
)
pause > nul
Forgive me if I'm reading this wrong, but isn't the "NOT" causing control to enter the bracketed if and run the broken output?
what about:
#echo off
echo Perfect output: %programFiles(x86)%
IF NOT "%programFiles(x86^)%" == "" (
REM Variable is defined
echo Broken output: %programFiles(x86)%
)
pause >nul
?
I have a batch file that runs several python scripts that do table modifications.
I want to have users comment out the 1-2 python scripts that they don't want to run, rather than removing them from the batch file (so the next user knows these scripts exist as options!)
I also want to add comments to bring to their attention specifically the variables they need to update in the Batch file before they run it. I see that I can use REM. But it looks like that's more for updating the user with progress after they've run it.
Is there a syntax for more appropriately adding a comment?
Use :: or REM
:: commenttttttttttt
REM commenttttttttttt
BUT (as people noted):
if they are not in the beginning of line, then add & character:
your commands here & :: commenttttttttttt
Inside nested parts (IF/ELSE, FOR loops, etc...) :: should be followed with normal line, otherwise it gives error (use REM there).
:: may also fail within setlocal ENABLEDELAYEDEXPANSION
The rem command is indeed for comments. It doesn't inherently update anyone after running the script. Some script authors might use it that way instead of echo, though, because by default the batch interpreter will print out each command before it's processed. Since rem commands don't do anything, it's safe to print them without side effects. To avoid printing a command, prefix it with #, or, to apply that setting throughout the program, run #echo off. (It's echo off to avoid printing further commands; the # is to avoid printing that command prior to the echo setting taking effect.)
So, in your batch file, you might use this:
#echo off
REM To skip the following Python commands, put "REM" before them:
python foo.py
python bar.py
No, plain old batch files use REM as a comment. ECHO is the command that prints something on the screen.
To "comment out" sections of the file you could use GOTO. An example of all these commands/techniques:
REM it starts here the section below can be safely erased once the file is customised
ECHO Hey you need to edit this file before running it! Check the instructions inside
ECHO Now press ctrl-c to interrupt execution or enter to continue
PAUSE
REM erase the section above once you have customised the file
python executed1.py
ECHO Skipping some stuff now
GOTO End
python skipped1.py
python skipped2.py
:END
python executed2.py
What can I say? batch files are a relic of times long gone, they're clunky and ugly.
You can read more on this website.
EDIT: modified the example a bit to have it contain the elements you are apparently looking for.
The :: instead of REM was preferably used in the days that computers weren't very fast.
REM'ed line are read and then ingnored. ::'ed line are ignored all the way. This could speed up your code in "the old days". Further more after a REM you need a space, after :: you don't.
And as said in the first comment: you can add info to any line you feel the need to
SET DATETIME=%DTS:~0,8%-%DTS:~8,6% ::Makes YYYYMMDD-HHMMSS
As for the skipping of parts.
Putting REM in front of every line can be rather time consuming.
As mentioned using GOTO to skip parts is an easy way to skip large pieces of code. Be sure to set a :LABEL at the point you want the code to continue.
SOME CODE
GOTO LABEL ::REM OUT THIS LINE TO EXECUTE THE CODE BETWEEN THIS GOTO AND :LABEL
SOME CODE TO SKIP
.
LAST LINE OF CODE TO SKIP
:LABEL
CODE TO EXECUTE
Multi line comments
If there are large number of lines you want to comment out then it will be better if you can make multi line comments rather than commenting out every line.
See this post by Rob van der Woude on comment blocks:
The batch language doesn't have comment blocks, though there are ways
to accomplish the effect.
GOTO EndComment1
This line is comment.
And so is this line.
And this one...
:EndComment1
You can use GOTO Label and :Label for making block comments.
Or, If the comment block appears at the end of the batch file, you can
write EXIT at end of code and then any number of comments for your
understanding.
#ECHO OFF
REM Do something
•
•
REM End of code; use GOTO:EOF instead of EXIT for Windows NT and later
EXIT
Start of comment block at end of batch file
This line is comment.
And so is this line.
And this one...
Putting comments on the same line with commands: use & :: comment
color C & :: set red font color
echo IMPORTANT INFORMATION
color & :: reset the color to default
Explanation:
& separates two commands, so in this case color C is the first command and :: set red font color is the second one.
Important:
This statement with comment looks intuitively correct:
goto error1 :: handling the error
but it is not a valid use of the comment. It works only because goto ignores all arguments past the first one. The proof is easy, this goto will not fail either:
goto error1 handling the error
But similar attempt
color 17 :: grey on blue
fails executing the command due to 4 arguments unknown to the color command: ::, grey, on, blue.
It will only work as:
color 17 & :: grey on blue
So the ampersand is inevitable.
You can comment something out using :: or REM:
your commands here
:: commenttttttttttt
or
your commands here
REM commenttttttttttt
To do it on the same line as a command, you must add an ampersand:
your commands here & :: commenttttttttttt
or
your commands here & REM commenttttttttttt
Note:
Using :: in nested logic (IF-ELSE, FOR loops, etc...) will cause an error. In those cases, use REM instead.
You can add comments to the end of a batch file with this syntax:
#echo off
:: Start of code
...
:: End of code
(I am a comment
So I am!
This can be only at the end of batch files
Just make sure you never use a closing parentheses.
Attributions: Leo Guttirez Ramirez on https://www.robvanderwoude.com/comments.php
Commenting a line
For commenting line use REM or :: though :: might fail inside brackets
within delayed expansion lines starting with !<delimiter> will be ignored so this can be used for comments:
#echo off
setlocal enableDelayedExpansion
echo delayed expansion activated
!;delayed expansion commented line
echo end of the demonstration
Comment at the end of line
For comments at the end of line you can again use rem and :: combined with &:
echo --- &:: comment (should not be the last line in the script)
echo --- &rem comment
Commenting at the end of file
As noting will be parsed after the exit command you can use it to put comments at the end of the file:
#echo off
echo commands
exit /b
-------------------
commnts at the end
of the file
------------------
Inline comments
Expansion of not existing variables is replaced with nothing ,and as setting a variable with = rather hard you can use this for inline comments:
#echo off
echo long command %= this is a comment =% with an inline comment
Multiline comments
For multiline comments GOTO (for outside brackets) and REM with conditional execution (for inside brackets) can be used. More details here:
#echo off
echo starting script
goto :end_comments
comented line
one more commented line
:end_comments
echo continue with the script
(
echo demonstration off
rem/||(
lines with
comments
)
echo multiline comment inside
echo brackets
)
And the same technique beautified with macros:
#echo off
::GOTO comment macro
set "[:=goto :]%%"
::brackets comment macros
set "[=rem/||(" & set "]=)"
::testing
echo not commented 1
%[:%
multi
line
comment outside of brackets
%:]%
echo not commented 2
%[:%
second multi
line
comment outside of brackets
%:]%
::GOTO macro cannot be used inside for
for %%a in (first second) do (
echo first not commented line of the %%a execution
%[%
multi line
comment
%]%
echo second not commented line of the %%a execution
)
I prefer to use:
REM for comments
&REM for inline comments
Example:
#echo off
set parameter1=%1%
REM test if the parameter 1 was received
if defined parameter1 echo The parameter 1 is %parameter1% &REM Display the parameter
This is an old topic and I'd like to add my understanding here to expand the knowledge of this interesting topic.
The key difference between REM and :: is:
REM is a command itself, while :: is NOT.
We can treat :: as a token that as soon as CMD parser encounters the first non-blank space in a line is this :: token, it will just skip the whole line and read next line. That's why REM should be followed by at least a blank space to be able to function as a comment for the line, while :: does not need any blank space behind it.
That REM is a command itself can be best understood from the following FOR syntax
The basic FOR syntax is as follows
FOR %v in (set) DO <Command> [command param]
here <Command> can be any valid command
So we can write the following valid command line as rem is a command
FOR %i in (1,2,3) DO rem echo %i
However, we CANNOT write the following line as :: is not a command
FOR %i in (1,2,3) DO :: echo %i
You can use :: or rem for comments.
When commenting, use :: as it's 3 times faster. An example is shown here
Only if comments are in if, use rem, as the colons could make errors, because they are a label.