Page 1 of 1

Safe REM with ampersand

Posted: 14 Jan 2016 09:03
by jeb
Hi,

from a SO topic How to reliably use `rem` within a command line without ignoring adjacent commands?.

Is there a way for a safe REM which executes an adjacent command.

Simple, but can fail when a file named REM exists

Code: Select all

REM. comment & echo My text


There seems also a difference if there is an ampersand or not.

Code: Select all

REM^;\..\x.bat & This works
REM But not the next line, it starts x.bat in the current directory
REM^;\..\x.bat


But my tests shows that these sample works always

Code: Select all

@echo off

echo 1
REM^= \..\x.bat
echo 2
REM^/ \..\x.bat
echo 3
REM^\ \..\x.bat
echo 4
REM^: \..\x.bat

REM^= \..\x.bat & echo 4
REM^/ \..\x.bat & echo 5
REM^\ \..\x.bat & echo 6
REM^: \..\x.bat & echo 7

Re: Safe REM with ampersand

Posted: 14 Jan 2016 10:04
by dbenham
Very interesting...

When I test your script on my Win 7 machine at work, every thing works.

But I swear when I tested something that I thought was equivalent on Win 10 at home, the stand-alone versions (without &) all failed. If I am correct, then this would be a somewhat shocking difference between Win 7 and Win 10. I'll double check again when I get home, or someone else with Win 10 could beat me to the punch.


Dave Benham

Re: Safe REM with ampersand

Posted: 14 Jan 2016 10:10
by dbenham
The other interesting part that I remember from my tests on Win 10 at home was that something like REM^, \..\x.bat worked on the command line, but failed in a batch script.

Re: Safe REM with ampersand

Posted: 14 Jan 2016 10:51
by dbenham
Also, the first test fails if file "rem=.bat" exists, even on Win 7.

Re: Safe REM with ampersand

Posted: 14 Jan 2016 20:17
by dbenham
OK, I somehow fooled myself with my Win 10 testing. I can't find any difference in behavior on this topic between Win 7 and Win 10 - thank goodness :!: :D

Where I ran into trouble was I had multiple batch files named things line "REM .BAT", "REM;.BAT", etc. And I did not structure them in a way that let me identify which one ran.

So when I tested something like

Code: Select all

REM^; \..\x.bat
I assumed it was x.bat that was running, when actually it was "REM;.BAT" that ran. So I arrived at the wrong conclusions as to what worked and what did not.

From what I can tell, the following form: rem<C><tokenDelimiter> works always when <C> is one of [backSlash], [forwardSlash], or [colon], and <tokenDelimiter> is one of [space], [tab], [0xFF], [comma], [semicolon], or [equal]. I don't see any need to escape the <C> character.

So all of the following work, even if x.bat exists in the current directory. Note - this is not an exhaustive list of all working permutations.

Code: Select all

@echo off

echo 1
REM\ \..\..\x.bat
echo 2
REM/ \..\..\x.bat
echo 3
REM: \..\x.bat

REM\ \..\..\x.bat & echo 4
REM/ \..\..\x.bat & echo 5
REM: \..\x.bat & echo 6

echo 7
REM:;\..\x.bat
echo 8
REM:,\..\x.bat
echo 9
REM:=\..\x.bat

REM:;\..\x.bat & echo 10
REM:,\..\x.bat & echo 11
REM:=\..\x.bat & echo 12

A critical component to why the above work is that : \ and / cannot appear in file names.

One additional form that seems to work is REM^[TAB]<tokenDelimiter>, but I'm not sure why. I can get the [TAB] in a file name, but the problem cases below don't seem to matter with [TAB].

As jeb already said, REM. is no good because it fails always if a file named "REM" (without an extension) exists in the current directory.

All the other candidates can fail in a batch file because they can appear in a file name. Note - only one of the following lines can be tested at a time

Code: Select all

REM^  This fails if "REM .BAT" exists
REM^; This fails if "REM;.BAT" exists
REM^, This fails if "REM,.BAT" exists
REM^= This fails if "REM=.BAT" exists
REM^[0xFF] This fails if "REM[0xFF].BAT" exists
REM[ This fails if "REM[.BAT" exists
REM] This fails if "REM].BAT" exists
REM+ This fails if "REM+.BAT" exists
But append & echo something to each line above, and they all work.

All potential characters can fail if there is not an unescaped token delimiter afterward because of the \..\x.bat issue. The unescaped token delimiter is required to disrupt the file path parsing.

So my results are similar to what jeb reported, accept
  • I don't see any need to escape the : / or \
  • = Cannot always be used safely, even if escaped


Dave benham