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.
Related
Full code below, sorry if the question looks jumbled.
I'm trying to make a batch file that adds a help doc to a specified directory, but the doc would need to have new lines. The problem is, is that I'm saving the text that gets put in the txt doc using a var.
I would like the help doc to look like this:
set help=helper \n new line \n\n more space
Which would look like this: (sorry, had to use code because a new line couldn't be made normally)
helper
new line
more space
I have seen things like the example down below, but when I do use this, the text in the doc just says echo is ON or echo is OFF, depending on whether or not echo is on (code found here):
setlocal EnableDelayedExpansion
set LF=^
rem TWO empty lines are required
echo This text!LF!uses two lines
And on top of that, this code looks like its new line var makes a spacer, rather than JUST a new line, like the, "helper," and, "new line," in the example I put above. I would want, "\n," to put the following text in the next line, and, "\n\n," to put the text two lines after the previous text, like, "more space," in the example above. In short, I'd like, "\n," to be a new line, and, "\n\n," to be a line break.
Thank you for taking the time to read this, I appreciate all answers and/or tips. If you're confused on anything that I mean, please feel free to ask me in the comments. I am pretty new to this, so my usage of some terminology is probably pretty poor. As well as that, sorry for the run on sentences and/or bad grammar/punctuation. I'm just a bit tired and I'm forgetting my English 1 classes, I suppose.
My full code is:
#echo off
:start
cls
echo -create
echo -download
echo.
set /p PROGRAM= What do you want to do?:
goto %PROGRAM%
:create
cls
REM saves the text types to the helpDir var
set /p helpDir=Where do you want to save the help file?:
REM makes the text used in the help.txt file, \n would be the new line,
set help=helper \n new line \n\n more space
REM I want to make it look like this:
REM helper
REM new line
REM
REM more space
REM Makes the "help" text to go to a .txt file, then saves the .txt file to the dir specified.
echo %help% > "%helpDir%\help.txt"
pause
goto start
REM not finished yet, please ignore
:download
title Custom Text File
cls
set /p help=Where do you want to save the help doc at?;
set /p txt=Made a command
echo %txt% > "dir
Pause
Your first sample works flawlessly, but today another style is prefered.
setlocal EnableDelayedExpansion
(set LF=^
%=DO NOT REMOVE THIS=%
)
echo This text!LF!uses two lines
If you see spaces in your output (instead of line feeds), check and remove trailing spaces in the LF definition.
From your comment, your problem is the percent expansion.
From your linked post:
The newline best works with delayed expansion, you can also use it
with the percent expansion, but then it's a bit more complex.
Simple rule: Always expand variables, containing line feed characters, only with delayed expansion.
set help=Line1 \n Line2
echo !help!>output.txt
i was toying around with cmd a bit and wanted to write a little application which involves a simple feature to read a counter from a txt file, then work with it and at the end raise the counter by one.
set /p x=<file.txt
...
set /a y=x+1
echo %y%>file.txt
Problem is it always returns "ECHO ist eingeschaltet (ON)." which translates to ECHO is turned on (ON) for some reason. Could somebody please explain where it comes from and how to fix it? I dont need anything fancy. I just want it to work and know where my mistake is.
At first, I want to show you how your echo command line should look like:
> "file.txt" echo(%y%
Here is your original line of code again:
echo %y%>file.txt
The reason for the unexpected output ECHO is on./ECHO is off. is because the echo command does not receive anything to echo (type echo /? and read the help text to learn what on/off means). Supposing y carries the value 2, the line expands to:
echo 2>file.txt
The number 2 here is not taken to be echoed here, it is consumed by the redirection instead; according to the article Redirection, 2> constitutes a redirection operator, telling to redirect the stream with the handle 2 (STDERR) to the given file. Such a handle can reach from 0 to 9.
There are some options to overcome that problem:
inserting a SPACE in between the echoed text and the redirection operator:
echo %y% >file.txt
the disadvantage is that the SPACE becomes part of the echoed text;
placing parentheses around the echo command:
(echo %y%)>file.txt
placing the redirection part at the beginning of the command line:
>file.txt echo %y%
I prefer the last option as this is the most general and secure solution. In addition, there is still room for improvement:
quote the file path/name to avoid trouble in case it contains white-spaces or other special characters;
use the odd syntax echo( to be able to output everything, even an empty string or literal strings like on, off and /?;
> "file.txt" echo(%y%
Hint:
To see what is actually going on, do not run a batch file by double-clicking on its icon; open a command prompt window and type its (quoted) path, so the window will remain open, showing any command echoes and error messages. In addition, for debugging a batch file, do not put #echo off on top (or comment it out by preceding rem, or use #echo on) in order to see command echoes.
Echo on means that everything that is executed in the batch is also shown in the console. So you see the command and on the following line the result.
You can turn this off with the echo off command or by preceding a # sign before the command you want to hide.
so
::turns of the echo for the remainder of the batch or untill put back on
::the command itself is not shwn because off the #
#echo off
set /p x=<file.txt
...
::the following won't be shown regardless the setting of echo
#set /a y = x+1
echo %y% > file.txt
EDIT after first comment
because your command echo %y%>file.txt doesn't work, you need a space before the > symbol, now you get the result of echo which gives you the current setting of echo
here a working sample, I put everything in one variable for sake of simplicity.
echo off
set /p x =< file.txt
set /a x += 1
echo %x% > file.txt
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.
I have three variables: string, search, replace. I wish to substitute the %search% in %string% with %replace%.
This works but needs hard characters.
SET modified=%string:morning=evening%
This seems to be answer in the forums but does not work. It simply stores the entire line at %modified%
SET modified=!string:%search%=%replace%!
The ! format is doing delayed expansion--the % variables get expanded immediately, but the ! variable gets expanded only when it's needed. I believe that only works in a batch file, so if you're experimenting directly at the command line you won't get the same behaviour as if you are running a batch file.
Make sure to enable delayed expansion in your batch file before using the ! notation, like this:
SETLOCAL ENABLEDELAYEDEXPANSION
SET string=This morning
SET search=morning
SET replace=evening
SET modified=!string:%search%=%replace%!
ECHO %modified%
ENDLOCAL
This will echo This evening.
How would I set a each line of a text document to separate variables using Batch? I know how to set a variable to the first line of a text document using:
Set /p Variable=<Test.txt
...but I don't know how to read other lines of the file. Lets say for example I had a text document with 3 lines, the first line had 'Apples' written on it, the second had 'Bananas' and the third had 'Pears', and lets say the document was called Fruit.txt. How would I set the variable 'Line_1' to the first line of the document, 'Line_2' to the second line and 'Line_3' to the last line?. Just to keep it simple, lets just say the batch file and Fruit.txt are both in the same folder. I don't want to do this in VBScript, so please only post Batch code. I would have thought that it would be something like:
#Echo off
Set /p Line_1=<Fruit.txt:1
Set /p Line_2=<Fruit.txt:2
Set /p Line_3=<Fruit.txt:3
Echo Fruit 1 is %Line_1%, Fruit 2 is %Line_2% and Fruit 3 is %Line_3%
Pause
Exit
...but quite clearly it isn't. Any help?
EDIT: This is for arbitrary-length files, then. jeb has an answer that solves your particular problem for a known number of lines. I will leave this here, though, as I hate deleting posts I put some time into for explanation :-)
Well, you obviously need some sort of counter. Let's start with 1:
set Counter=1
Then, you need to go line-wise through the file:
for /f %%x in (somefile) do ...
Then store the line in a numbered variable (that's what we have the counter for):
set "Line_!Counter!=%%x"
aaaaand increment the counter:
set /a Counter+=1
And that's it. Add a few more necessary things, you know, the boring stuff that's always needed in such cases (strange statements before and after, block delimiters, etc.), and you're done:
#echo off
setlocal enabledelayedexpansion
set Counter=1
for /f %%x in (somefile) do (
set "Line_!Counter!=%%x"
set /a Counter+=1
)
set /a NumLines=Counter - 1
Echo Fruit 1 is %Line_1%, Fruit 2 is %Line_2% and Fruit 3 is %Line_3%
rem or, for arbitrary file lengths:
for /l %%x in (1,1,%NumLines%) do echo Fruit %%x is !Line_%%x!
Some explanation:
set /p Var=<file will set the variable to the first line of a file, as you noted. That works because set /p will prompt for input and < file will redirect the file into standard input of a command. Thus set /p will interpret the file's contents as the entered input up until the user hits Return (i.e. the file contains a line break). That's why you get the first line. The system would throw the whole file at set /p but since the command only reads the first line and then is done they just get discarded.
The syntax you were proposing there is actually for accessing Alternate Data Streams of files on NTFS, which is somethhing totally different.
<short-detour> However, jeb has a way of reading multiple lines. This works because the block (delimited by parentheses) is a single command (see below) you can redirect a file's contents into. Except that command is comprised of multiple statements, each of which will read a single line and store it away. </short-detour>
Which brings us to for /f which iterates over the contents of a file (or the output of a command) line by line and executes a command or block of commands for each line. We can now read the whole file into as many variables as there are lines. We don't even need to know how many in advance.
You may have noticed the Line_!Counter! in there which uses Counter a little bit differently from how you're used to use environment variables, I guess. This is called delayed expansion and is necessary in some cases due to how cmd parses and executes batch files. Environment variables in a command are expanded to their values upon parsing that command. In this case the whole for /f including the block containing two statements is a single command for cmd. So if we used %Counter% it would be replaced by the value Counter had before the loop (1) and never change while the loop is running (as it is parsed once and run multiple times. Delayed expansion (signaled by using ! instead of % for variable access changes that and expands environment variables just prior to running a command.
This is almost always necessary if you change a variable within a loop and use it within the same loop again. Also this makes it necessary to first enable delayed expansion which is done with the setlocal command and an appropriate argument:
setlocal enabledelayedexpansion
set /a will perform arithmetic. We use it here to increment Counter by one for each line read.
To read multiple lines with set/p you need brackets around the set/p block.
#Echo off
(
Set /p Line_1=
Set /p Line_2=
Set /p Line_3=
) <Fruit.txt
Echo Fruit 1 is %Line_1%, Fruit 2 is %Line_2% and Fruit 3 is %Line_3%