Surprising difference between command line and batch

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
dbenham
Expert
Posts: 2389
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Surprising difference between command line and batch

#1 Post by dbenham » 09 Feb 2020 16:04

I was messing around with escaped token delimiters, and I discovered a difference between command line and batch contexts.

A batch script allows you to execute a command with escaped spaces (or any token delimiter) within the name. Note that a name cannot be called with escapes directly because CALL doubles all carets, so the token delimiters are no longer escaped. Instead a variable must be defined and then use CALL %%VAR%%.

The command line does not allow this unless the very first character of the name(or path) is an escaped token delimiter. If the first character is an escaped token delimiter, then any number of escaped token delimiters can appear anywhere else in the name.

I have the same script under two names:
"a b.bat"
" a b.bat"

Code: Select all

executing "%~nx0"
And here is my test.bat

Code: Select all

@echo off
setlocal
set "var=%~1"
<nul set /p "=Command Line NO CALL: "
cmd /c %1
<nul set /p "=Batch File      CALL: "
call %%var%%
<nul set /p "=Batch File   NO CALL: "
%~1
And finally a bunch of test runs:

Code: Select all

>test "a^ b"
Command Line NO CALL: 'a' is not recognized as an internal or external command,
operable program or batch file.
Batch File      CALL: executing "a b.bat"
Batch File   NO CALL: executing "a b.bat"

>test "^ a^ b"
Command Line NO CALL: executing " a b.bat"
Batch File      CALL: executing " a b.bat"
Batch File   NO CALL: executing " a b.bat"

>test "^ \x^ y^ ^z\..\..\a^ b"
Command Line NO CALL: executing "a b.bat"
Batch File      CALL: executing "a b.bat"
Batch File   NO CALL: executing "a b.bat"

>test "x^ \x^ y^ ^z\..\..\a^ b"
Command Line NO CALL: 'x' is not recognized as an internal or external command,
operable program or batch file.
Batch File      CALL: executing "a b.bat"
Batch File   NO CALL: executing "a b.bat"
Dave Benham

penpen
Expert
Posts: 1864
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Surprising difference between command line and batch

#2 Post by penpen » 09 Feb 2020 18:36

It seems like escaping a character that doesn't need escaping doesn't count as beeing escaped:

Code: Select all

>test "^a^ b.bat"
var=^a^ b.bat
Command Line NO CALL: Der Befehl "a" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.
Batch File      CALL: executing "a b.bat"
Batch File   NO CALL: executing "a b.bat"

>test "^,a^ b.bat"
var=^,a^ b.bat
Command Line NO CALL: executing ",a b.bat"
Batch File      CALL: executing ",a b.bat"
Batch File   NO CALL: executing ",a b.bat"

>test "^+a^ b.bat"
var=^+a^ b.bat
Command Line NO CALL: executing "+a b.bat"
Batch File      CALL: executing "+a b.bat"
Batch File   NO CALL: executing "+a b.bat"
(Sidenote: Needs additional files.)


penpen

dbenham
Expert
Posts: 2389
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Surprising difference between command line and batch

#3 Post by dbenham » 09 Feb 2020 21:37

Yes, I did that test, but forgot to include it. It was important to how I ultimately described what I was seeing on the command line.

jeb
Expert
Posts: 967
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: Surprising difference between command line and batch

#4 Post by jeb » 10 Feb 2020 02:22

Very strange :shock:

Especially penpen's test with a starting "+".
"+" isn't a delimiter, but it is handled different than a letter :!:
But "-" works like a letter :?:

Code: Select all

test "aaa^ b"  -- fails
test "^aaa^ b"  -- fails

test "^+aa^ b" --- works
test "+aa^ b" --- works

test "^-aa^ b" --- FAILS
test "-aa^ b" --- FAILS

dbenham
Expert
Posts: 2389
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Surprising difference between command line and batch

#5 Post by dbenham » 10 Feb 2020 06:16

:shock: Oh! I didn't look at penpen's tests close enough. I missed the + test. That is strange!

And your test without escaping the + is even stranger! Why on earth is phase 2 concerned about + :?: :? Where is + special in CMD, other than COPY?

jeb
Expert
Posts: 967
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: Surprising difference between command line and batch

#6 Post by jeb » 10 Feb 2020 07:37

I believe that phase 2 isn't related to this effect.

Proof by showing that phase 2 only detects one complete command token

abc.bat

Code: Select all

@echo off
echo This is "%~0"
setlocal EnableDelayedExpansion
echo ccl: "!cmdcmdline!"

setlocal DisableDelayedExpansion
prompt ###$G
echo on
REM # %0 #
REM # %1 #
@echo off
TEST.bat

Code: Select all

@echo off
setlocal
set "var=%~1"
echo "%var%"
<nul set /p "=Command Line NO CALL: "
cmd /v:on /c %1
And now three tests

Code: Select all

C:\Temp>TEST.bat "ab^^c^ def.bat"
"ab^^c^ def.bat"
Command Line NO CALL: 'ab^c' is not recognized as an internal or external command,
operable program or batch file.


C:\Temp>TEST.bat "ab^^c d!!ef.bat"
"ab^^c d!!ef.bat"
Command Line NO CALL: 'ab^c' is not recognized as an internal or external command,
operable program or batch file.


C:\Temp>TEST.bat "ab^^c^ d!!ef.bat"
"ab^^c^ d!!ef.bat"
Command Line NO CALL: This is "abc"
ccl: "cmd  /v:on /c "ab^^c^ d!!ef.bat""

###>REM # abc #

###>REM # d!!ef.bat #
Only the last test executes abc.bat, but this only works, because the command token has to be the complete string!
Therefor the caret between "ab" and "c" is removed in the delayed expansion phase.
But later the command token is splitted again into "abc" and "d!!ef.bat".

But that can't be phase 2, it must be the mysterious phase 7.

jeb

dbenham
Expert
Posts: 2389
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Surprising difference between command line and batch

#7 Post by dbenham » 10 Feb 2020 09:08

Ohhhh! Nice analysis. I forgot to consider phase 7.

So Phase 7 must be different for the command line mode. For Batch we currently have
StackOverflow wrote:
  • 7.3 - Execute external command - Else try to treat the command as an external command.
    • If in command line mode and the command is not quoted and does not begin with a volume specification, then break the command token at the first occurrence of <space> , ; or = and prepend the remainder to the argument token(s).
    • . . .
I'm guessing that phase 7 in command line mode does not break the command token at the first <space> , ; or = if the command token begins with a whitespace , ; = or +

It still is a mystery as to why the command line would care about +

scavenger
Posts: 18
Joined: 23 May 2015 13:51
Contact:

Re: Surprising difference between command line and batch

#8 Post by scavenger » 10 Feb 2020 14:56

that's what I love with MSDOS. it's clearly a monstrosity made of different pieces developed by different teams over the last 30 years, and you cannot guess correctly at 100% any outcome until you actually test all cases. ss64.com clearly highlight that fact with "works but undocumented" comments everywhere lol

Post Reply