I am trying to use the rem
command to place a remark in a command line that contains several commands. Here are some examples to illustrate what I mean:
echo Hello & rem.Comment & echo world!
(echo Hello & rem.Comment) & echo world!
This works perfectly fine, both echo
commands in each line are executed as I expect. The .
seems to modify the behaviour of the rem
command so that it does not treat the remaining line as comment:
Hello world!
If I placed a SPACE (or any other delimiter TAB, ,
, ;
, =
) instead of the .
, the remaining line and therefore the second echo
would be ignored (for the second example a More?
prompt appears, because the )
is part of the remark and cmd
expects a closing )
because of the (
):
Hello
I found out that beside .
, the following characters work as well: :
, /
, \
, [
, ]
and +
.
What else works is escaped delimiters: ^
SPACE, ^
TAB, ^,
, ^;
and ^=
.
Nevertheless, is there a secure and reliable way to do that?
I would be very glad about a solution that works for both command prompt and batch-files.
According to this external reference, the familiar syntax echo.
for returning a blank line fails under certain circumstances, hence using echo(
is recommended as this is the only reliable method.
However, for rem
, the (
does not work, everything after rem(
is not recognised as a command.
Since I am aware of a weird bug of the rem
command in Windows XP (reference this external link: rem %~
), I am interested in a solution that applies to Windows Vista, Windows 7 or higher.
REM [comment] Purpose: Provides a way to insert remarks (that will not be acted on) into a batch file. Discussion. During execution of a batch file, DOS will display (but not act on) comments which are entered on the line after the REM command. You cannot use separators in the comment except the space, tab, and comma.
The "weird" REM %~
"bug" is not limited to XP. It is present in all modern versions of Windows that use CMD.EXE. After reading your question, I wrote Simon of SS64 a note to give clarification on the issue. REM can also fail if variable var exists, and you have rem %var:=
.
So technically, there is no guaranteed safe way to blindly use REM.
But, if you are willing to accept the fatal % expansion risk, most of your listed hacks are safe to use, but only if the line includes at least one additional command via &
or &&
.
REM.
is never safe to use in any situation if there exists a file named REM
(without extension).
The folder dividers \
and /
always fail if the current folder contains a file named test.bat
and you use REM\..\test.bat
.
In a similar fashion, REM:\..\test.bat
always fails.
Every one of the other hacks can fail stand-alone in a similar situation. For example, REM^[tab]\..\test.bat
fails stand-alone, but works if concatenated with another command. This is the only type of situation I've found where +
, [
, ]
, or ^[tab]
can fail.
There are additional cases where some of the other hacks can fail.
Any character in the set C (^[space]
, ^,
, ^;
, ^=
) that are valid in file names can fail stand-alone if remC.bat
exists. For example, the following fails stand-alone:
rem^ Fails if "rem .bat" exists
Yet they are all safe when concatenated with another command:
echo OK&rem^ This is safe
rem^ This is safe &echo OK
Temporary Update
Some of the above is wrong. Investigations are ongoing at http://www.dostips.com/forum/viewtopic.php?f=3&t=6895&p=44813#p44813.
I believe the following are the simplest forms that are guaranteed to work in all cases (disregarding invalid % expansion)
REM: At least one space (or other token delimiter) must be after :
REM\ At least one space (or other token delimiter) must be after \
REM/ At least one space (or other token delimiter) must be after /
REM^[tab] At lease one space (or other token delimiter) must be after [tab]
But I won't correct the earlier info until the dust has settled
End Temporary Update
My favorite way to use inline comments is to use impossible variables. Only dynamic pseudo variables can contain =
in a name, and no variable name can ever contain two =
. So I like to use %= Remark goes here =%
. The beauty of this form is it can be used pretty much anywhere with impunity, as long as the comment does not contain %
or :
. It can even be used safely within parenthesized blocks of code.
for %%F in (*) do (
%= Comment within code block =%
%= 2nd comment within code block =%
FINDSTR /B %=Must match beginning of line=% "string" %= Search string =% "%%F" %= File to search =%
)
This variants of REM seems to be a safe way to enable the &
sign in the comment part.
REM/
REM\
REM:
Despite of @dbenham's comment, I can't create any file which would iterfere with these REM variants (I tried REM.bat
, REM;.bat
and so on).
It's always a good idea to add a space after the REM^<char>
.
The problem with %~
can't be solved, as the cmd.exe uses multiple parser phases for each line.
And the %~
error is detected in an early phase (percent expansion phase), just before the phase where a REM
would be detected.
But at all, I prefere percent comments for inline comments, described by dbenham
EDIT:
I removed the carets from REM^<char>
as it's doesn't matter.
Normally a REM
remarks the rest of the line, as the batch parser detects the REM
keyword in phase2 of the parser and switches to a specialized parser only for REM.
But when a character is appended to REM
the keyword will nt be detected in phase2.
If the character is one of \/;,=+(
the parser will remove it later and executes a normal REM command.
That's the cause why the command operators &
, &&
, |
, ||
can be recognized in this case.
Why rem/ | break
fails, but (REM/) | break
works?
It's because the pipe starts two seperate cmd child processes.
With surrounding parenthesis the command will be parsed the first time in the child process.
But without parenthesis, the parent process has already parsed the REM/
and checks if the file exists (but doesn't execute it).
But when such a file exists then the parser is smart enough to remove the seperator character and detects that REM
is an internal command.
This behaviour looks a bit strange.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With