Back to jeb's phase 7 token delimiter tests. I wondered if <LF> and <CR> might have any effect on any other ECHO white space characters besides <space> and <tab>. I also wanted to cleanup the rules a little bit.
So I did some more tests - What a can of worms this turned out to be
First I will state my new discoveries / rules. Later on I will provide the evidence in the form of scripts and output.
1) I discovered two additional phase 2 token delimiters
- <VT> 0x0B Vertical tab
- <FF> 0x0C Form Feed
So the complete list of standard phase 2 token delimiters is
<space> <tab> , ; = <VT> <FF> <NBSP> (Non-Breaking Space 0xFF)
In addition, there is the special command token delimiter
( that only serves as the stop character for a command token.
After discovering these, I decided to test all control characters from 0x01 - 0x1F (test not shown), and I did not find any additional ones.
2) I refined the list of phase 7 command token delimiters
- Class 1 (rarely fails): <space> <tab> , ; = + / [ ]
- Class 2 (sometimes fails): \ . :
Note that the following phase 2 token delimiters are
not included:
( <VT> <FF> <LF> <CR> <NBSP>
The command token delimiter is always included in the arguments list for the internal command. How it is interpreted is up to the individual command.
3) The odd phase 7 ECHO behavior that jeb discovered regarding <LF> <CR> and <NBSP> does not work on all machines
For this discussion, I will call the odd behavior
"Extended ECHO"
I tested jeb's script on 3 machines, and I was only able to reproduce his Extended ECHO results on one of them.
I cannot figure out any predictor as to when Extended ECHO works
Windows 7 Desktop: Extended ECHO works
Code: Select all
INFO.BAT version 1.4
--------------------------------------------------------------------------------
Windows version : Microsoft Windows [Version 6.1.7601]
Product name : Windows 7 Enterprise, 32 bit
Performance indicators : Processor Cores: 4 Visible RAM: 3659760 kilobytes
Date/Time format : (mm/dd/yy) 02/05/2018 12:46:47.06
__APPDIR__ : C:\Windows\System32\
ComSpec : C:\Windows\system32\cmd.exe
PathExt : .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.sh;.ksh;.csh;.sed;.awk;.pl
Extensions : system: Enabled user: Enabled
Delayed expansion : system: Disabled user: Disabled
Locale name : en-US Code Pages: OEM 437 ANSI 1252
DIR format : 02/02/2018 09:44 PM 3,747,594,240 pagefile.sys
Permissions : Elevated Admin=No, Admin group=No
Windows 7 Laptop: Extended ECHO fails
Code: Select all
INFO.BAT version 1.4
--------------------------------------------------------------------------------
Windows version : Microsoft Windows [Version 6.1.7601]
Product name : Windows 7 Enterprise, 32 bit
Performance indicators : Processor Cores: 8 Visible RAM: 3058776 kilobytes
Date/Time format : (mm/dd/yy) Mon 02/05/2018 12:48:42.19
__APPDIR__ : C:\windows\system32\
ComSpec : C:\windows\system32\cmd.exe
PathExt : .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
Extensions : system: Enabled user: Enabled
Delayed expansion : system: Disabled user: Disabled
Locale name : en-US Code Pages: OEM 437 ANSI 1252
DIR format : 02/05/2018 07:17 AM 3,132,186,624 pagefile.sys
Permissions : Elevated Admin=No, Admin group=No
Windows 10 Desktop: Extended ECHO fails
Code: Select all
INFO.BAT version 1.4
--------------------------------------------------------------------------------
Windows version : Microsoft Windows [Version 10.0.16299.125]
Product name : Windows 10 Pro, 64 bit
Performance indicators : Processor Cores: 4 Visible RAM: 4192432 kilobytes
Date/Time format : (mm/dd/yy) Mon 02/05/2018 23:47:16.85
__APPDIR__ : C:\WINDOWS\system32\
ComSpec : C:\WINDOWS\system32\cmd.exe
PathExt : .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
Extensions : system: Enabled user: Enabled
Delayed expansion : system: Disabled user: Disabled
Locale name : en-US Code Pages: OEM 437 ANSI 1252
DIR format : 02/04/2018 07:20 PM 4,445,007,872 pagefile.sys
Permissions : Elevated Admin=No, Admin group=Yes
Missing from the tool collection: debug
4) I refined the phase 7 rules for Extended ECHO behavior
- The list of phase 7 Extended ECHO delimiters is <LF> <CR> <VT> <FF> <NBSP>
- The Extended ECHO delimiters work only for the ECHO command, and only in phase 7
- If the ECHO command is delimited by an Extended ECHO delimiter in phase 7, then:
- The Extended ECHO delimiter is output normally - it is not stripped like most command delimiters
- Each contiguous string of <space> and/or <tab> is collapsed into a single <space>
And below are my "proofs" for the above:
TEST1.bat
Code: Select all
@echo off
setlocal disableDelayedExpansion
cls
for /f "tokens=1-6 delims= " %%A in (
'forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(0x08 0x09 0x0B 0x0C 0x1A 0xFF"'
) do (
set "BS=%%A
set "TAB=%%B"
set "VT=%%C"
set "FF=%%D"
set "SUB=%%E"
set "NBSP=%%F"
set "SP= "
set "SC=;"
set "COM=,"
set "EQ=="
set "LP=("
)
(set LF=^
%= empty line creates <LF> character =%
)
for /F %%# in ('copy /Z "%~dpf0" NUL') do set "CR=%%#"
set "###CMD= "
call :test "%%%%NBSP%%%% = 0xFF" "%NBSP%"
call :test "!NBSP! = 0xFF" !NBSP!
call :test !LF! !LF!
call :test !CR! !CR!
call :test ( (
call :test "!LP! = (" !LP!
call :test "%%%%BS%%%% = 0x08" "%BS%"
call :test "%%%%VT%%%% = 0x0B" "%VT%"
call :test "%%%%FF%%%% = 0x0C" "%FF%"
call :test "%%%%SUB%%%% = 0x1A" "%SUB%"
call :test "!BS! = 0x08" !BS!
call :test "!VT! = 0x0B" !VT!
call :test "!FF! = 0x0C" !FF!
call :test "!SUB! = 0x1A" !SUB!
call :test !SP! !SP!
call :test !TAB! !TAB!
call :test "!SC! = ;" !SC!
call :test "!COM! = ," !COM!
call :test "!EQ! = =" !EQ!
call :test [ [
call :test ] ]
call :test + +
call :test / /
call :test . .
call :test \ \
call :test : :
exit /b
:test
echo(&echo(Test %~1 %~2
setlocal enableDelayedExpansion
<nul set/p"=---"
echo%~2#^ ^ #!TAB!!TAB!!VT!!VT!!FF!!FF!!NBSP!!NBSP!^,^,^;^;^=^=!LF!---!CR!!###CMD: =ARG^^!^
^ #!TAB!!TAB!!VT!!VT!!FF!!FF!!NBSP!!NBSP!^,^,^;^;^=^=!LF!---!CR!!###CMD: =ARG^^!
exit /b
test1 output on machine
with Extended ECHO support:
Code: Select all
Test %NBSP% = 0xFF
---# # ♂♂♀♀ ,,;;==
ARG^ # ♂♂♀♀ ,,;;==
ARG^
Test !NBSP! = 0xFF !NBSP!
--- # # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test !LF! !LF!
---
# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test !CR! !CR!
# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test ( (
---# # ♂♂♀♀ ,,;;==
ARG^ # ♂♂♀♀ ,,;;==
ARG^
Test !LP! = ( !LP!
---'echo(#' is not recognized as an internal or external command,
operable program or batch file.
Test %BS% = 0x08
---'ech#' is not recognized as an internal or external command,
operable program or batch file.
Test %VT% = 0x0B ♂
---# # ♂♂♀♀ ,,;;==
ARG^ # ♂♂♀♀ ,,;;==
ARG^
Test %FF% = 0x0C ♀
---# # ♂♂♀♀ ,,;;==
ARG^ # ♂♂♀♀ ,,;;==
ARG^
Test %SUB% = 0x1A →
---'echo→#' is not recognized as an internal or external command,
operable program or batch file.
Test !BS! = 0x08 !BS!
---'ech#' is not recognized as an internal or external command,
operable program or batch file.
Test !VT! = 0x0B !VT!
---♂# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test !FF! = 0x0C !FF!
---♀# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test !SUB! = 0x1A !SUB!
---'echo→#' is not recognized as an internal or external command,
operable program or batch file.
Test !SP! !SP!
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test !TAB! !TAB!
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test !SC! = ; !SC!
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test !COM! = , !COM!
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test !EQ! = = !EQ!
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test [ [
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test ] ]
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test + +
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test / /
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test . .
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test \ \
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test : :
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
test1.bat output on a machine
without Extended ECHO support:
Code: Select all
Test %NBSP% = 0xFF
---# # ♂♂♀♀ ,,;;==
ARG^ # ♂♂♀♀ ,,;;==
ARG^
Test !NBSP! = 0xFF !NBSP!
---'echo' is not recognized as an internal or external command,
operable program or batch file.
Test !LF! !LF!
---'echo' is not recognized as an internal or external command,
operable program or batch file.
Test !CR! !CR!
---'echo' is not recognized as an internal or external command,
operable program or batch file.
Test ( (
---# # ♂♂♀♀ ,,;;==
ARG^ # ♂♂♀♀ ,,;;==
ARG^
Test !LP! = ( !LP!
---'echo(#' is not recognized as an internal or external command,
operable program or batch file.
Test %BS% = 0x08
---'ech#' is not recognized as an internal or external command,
operable program or batch file.
Test %VT% = 0x0B ♂
---# # ♂♂♀♀ ,,;;==
ARG^ # ♂♂♀♀ ,,;;==
ARG^
Test %FF% = 0x0C ♀
---# # ♂♂♀♀ ,,;;==
ARG^ # ♂♂♀♀ ,,;;==
ARG^
Test %SUB% = 0x1A →
---'echo→#' is not recognized as an internal or external command,
operable program or batch file.
Test !BS! = 0x08 !BS!
---'ech#' is not recognized as an internal or external command,
operable program or batch file.
Test !VT! = 0x0B !VT!
---'echo' is not recognized as an internal or external command,
operable program or batch file.
Test !FF! = 0x0C !FF!
---'echo' is not recognized as an internal or external command,
operable program or batch file.
Test !SUB! = 0x1A !SUB!
---'echo→#' is not recognized as an internal or external command,
operable program or batch file.
Test !SP! !SP!
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test !TAB! !TAB!
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test !SC! = ; !SC!
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test !COM! = , !COM!
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test !EQ! = = !EQ!
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test [ [
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test ] ]
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test + +
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test / /
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test . .
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test \ \
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
Test : :
---# # ♂♂♀♀ ,,;;==
###CMD: =ARG! # ♂♂♀♀ ,,;;==
ARG^
TEST2.BAT
Code: Select all
@echo off
setlocal disableDelayedExpansion
cls
for /f "tokens=1-6 delims= " %%A in (
'forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(0x08 0x09 0x0B 0x0C 0x1A 0xFF"'
) do (
set "BS=%%A
set "TAB=%%B"
set "VT=%%C"
set "FF=%%D"
set "SUB=%%E"
set "NBSP=%%F"
set "SP= "
set "SC=;"
set "COM=,"
set "EQ=="
set "LP=("
)
(set LF=^
%= empty line creates <LF> character =%
)
for /F %%# in ('copy /Z "%~dpf0" NUL') do set "CR=%%#"
set "###CMD= "
call :test [
call :test ]
call :test +
call :test !SP!
call :test !TAB!
call :test !EQ!
call :test !COM!
call :test !SC!
call :test !EQ!
call :test !LF!
call :test !CR!
call :test !VT!
call :test !FF!
call :test !NBSP!
exit /b
:test
setlocal enableDelayedExpansion
echo(
echo on
echo%~1 ECHO works
type%~1
set%~1xxx
@echo off
exit /b
test2.bat output on machine with Extended ECHO support
Code: Select all
P:\test>echo[ ECHO works
ECHO works
P:\test>type[
The system cannot find the file specified.
P:\test>set[xxx
Environment variable [xxx not defined
P:\test>echo] ECHO works
ECHO works
P:\test>type]
The system cannot find the file specified.
P:\test>set]xxx
Environment variable ]xxx not defined
P:\test>echo+ ECHO works
ECHO works
P:\test>type+
The system cannot find the file specified.
P:\test>set+xxx
Environment variable +xxx not defined
P:\test>echo!SP! ECHO works
ECHO works
P:\test>type!SP!
The syntax of the command is incorrect.
P:\test>set!SP!xxx
Environment variable xxx not defined
P:\test>echo!TAB! ECHO works
ECHO works
P:\test>type!TAB!
The syntax of the command is incorrect.
P:\test>set!TAB!xxx
Environment variable xxx not defined
P:\test>echo!EQ! ECHO works
ECHO works
P:\test>type!EQ!
The syntax of the command is incorrect.
P:\test>set!EQ!xxx
The syntax of the command is incorrect.
P:\test>echo!COM! ECHO works
ECHO works
P:\test>type!COM!
The syntax of the command is incorrect.
P:\test>set!COM!xxx
Environment variable ,xxx not defined
P:\test>echo!SC! ECHO works
ECHO works
P:\test>type!SC!
The syntax of the command is incorrect.
P:\test>set!SC!xxx
Environment variable ;xxx not defined
P:\test>echo!EQ! ECHO works
ECHO works
P:\test>type!EQ!
The syntax of the command is incorrect.
P:\test>set!EQ!xxx
The syntax of the command is incorrect.
P:\test>echo!LF! ECHO works
ECHO works
P:\test>type!LF!
'type' is not recognized as an internal or external command,
operable program or batch file.
P:\test>set!LF!xxx
'set' is not recognized as an internal or external command,
operable program or batch file.
P:\test>echo!CR! ECHO works
ECHO works
P:\test>type!CR!
'type' is not recognized as an internal or external command,
operable program or batch file.
P:\test>set!CR!xxx
'set' is not recognized as an internal or external command,
operable program or batch file.
P:\test>echo!VT! ECHO works
♂ ECHO works
P:\test>type!VT!
'type' is not recognized as an internal or external command,
operable program or batch file.
P:\test>set!VT!xxx
'set' is not recognized as an internal or external command,
operable program or batch file.
P:\test>echo!FF! ECHO works
♀ ECHO works
P:\test>type!FF!
'type' is not recognized as an internal or external command,
operable program or batch file.
P:\test>set!FF!xxx
'set' is not recognized as an internal or external command,
operable program or batch file.
P:\test>echo!NBSP! ECHO works
ECHO works
P:\test>type!NBSP!
'type' is not recognized as an internal or external command,
operable program or batch file.
P:\test>set!NBSP!xxx
'set' is not recognized as an internal or external command,
operable program or batch file.
TEST3.BAT
Code: Select all
@echo off
setlocal disableDelayedExpansion
cls
for /f "tokens=1-2 delims= " %%A in (
'forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(0x0B 0x0C"'
) do (
set "VT=%%A"
set "FF=%%B"
)
echo on
cmd /c for %%. in (.) do if a%VT%b==a%VT%b echo VT OK
cmd /c for %%. in (.) do if a%FF%b==a%FF%b echo FF OK
cmd /v:on /c for %%. in (.) do if a!VT!b==a!VT!b echo VT OK
cmd /v:on /c for %%. in (.) do if a!FF!b==a!FF!b echo FF OK
test3.bat output
Code: Select all
P:\test>cmd /c for %. in (.) do if a♂b==a♂b echo VT OK
b==a was unexpected at this time.
P:\test>cmd /c for %. in (.) do if a♀b==a♀b echo FF OK
b==a was unexpected at this time.
P:\test>cmd /v:on /c for %. in (.) do if a!VT!b==a!VT!b echo VT OK
P:\test>if a!VT!b == a!VT!b echo VT OK
VT OK
P:\test>cmd /v:on /c for %. in (.) do if a!FF!b==a!FF!b echo FF OK
P:\test>if a!FF!b == a!FF!b echo FF OK
FF OK
Dave Benham