(Very) Small Difference in Batch Parameters %* and %$

Dec 29, 2021
18
2
$* the complete command tail, unmodified by SHIFT
%$ the complete command tail, modified by SHIFT

We do not uses SHIFT very often so we mixed up these two parameters.

On one occasion its was fatal..

It is a minor issue with a very easy workaround.

[R:\] type SetPath.btm setlocal echo TCCVer=%@verinfo[%_cmdspec,Fileversion] OSBuild=%_OSBuildEx set path_to_added=C:\ ECHO. ECHOX %$ the complete command tail, modified by SHIFT ALIAS SETPATH=SET PATH=`C:\Windows;%$` SETPATH %path_to_added ECHO PATH=%PATH PATH/N PATH/V ECHO. ECHOX %* the complete command tail, unmodified by SHIFT ALIAS SETPATH=SET PATH=`C:\Windows;%*` SETPATH %path_to_added ECHO PATH=%PATH PATH/N PATH/V [R:\] call SetPath.btm TCCVer=28.02.18 OSBuild=22000.376 %$ the complete command tail, modified by SHIFT PATH=C:\Windows;C:\ C:\Windows C:\ %* the complete command tail, unmodified by SHIFT PATH=C:\Windows; C:\ C:\Windows C:\ TCC: (Sys) R:\SetPath.btm [20] The system cannot find the path specified. " C:\"

The extra space before C invalidates the PATH.
We do not use SHIFT and expected the two batch parameters are exactly the same.
 
  • Like
Reactions: Alpengreis
Can reproduce that with following:

Code:
@echo off

echo.
set toadd=C:\
echox %$ The complete command tail, modified by SHIFT
alias testalias1=set testvar1=`C:\Windows;%$`
testalias1 %toadd
echo testvar1=%testvar1
unalias testalias1
unset toadd
unset testvar1

echo.
set toadd=C:\
echox %* The complete command tail, unmodified by SHIFT
alias testalias1=set testvar1=`C:\Windows;%*`
testalias1 %toadd
echo testvar1=%testvar1
unalias testalias1
unset toadd
unset testvar1

Code:
%$ The complete command tail, modified by SHIFT
testvar1=C:\Windows;C:\

%* The complete command tail, unmodified by SHIFT
testvar1=C:\Windows; C:\

EDIT: However, with the first try, the command tail doesn't work!
EDIT2: Replaced example with better code ...
 
Last edited:
Seems it's realated to ALIAS, because in the following example, BOTH have a leading space:

Code:
@echo off

set toadd=C:\

echo.
echox %$ The complete command tail, modified by SHIFT
set testvar1=`C:\Windows;%$` %toadd
echo testvar1=%testvar1
echo.
echox %* The complete command tail, unmodified by SHIFT
set testvar1=`C:\Windows;%*` %toadd
echo testvar1=%testvar1

Code:
%$ The complete command tail, modified by SHIFT
testvar1=C:\Windows; C:\

%* The complete command tail, unmodified by SHIFT
testvar1=C:\Windows; C:\

EDIT: NOT TRUE, was only because not unset related var(s).
 
Last edited:
Code:
@echo off
setlocal

alias `test1=echo "%$"`
alias `test2=echo "%*"`

echo These two aliases look similar, but they do very different things.
echo TEST1 echos ITS OWN parameters, in quotes:
echo.

test1 One two three

echo.
echo But TEST2 echos any BATCH FILE'S parameters, in quotes, followed
echo by its own, if any:
echo.

test2 One two three

echo.
echo Try calling this batch files with different parameters to see how
echo this works.
echo.

endlocal
 
I'm going to explain this again, in a different way. In an alias, %$ expands to the alias's parameters. %* is always and only batch file parameters; it has no special meaning to the alias mechanism.

If an alias definition does not explicitly refer to its parameters with %$ (or %1, %1$, whatever), they will get tacked on automatically, with a space separator. That's where that mysterious space is coming from.

Code:
C:\>alias foo=`echo !`

C:\>foo
!

C:\>foo bar baz quux
! bar baz quux

C:\>

If you don't want this to happen, you can add a REM to the end to 'swallow' the unwanted args:

Code:
C:\>alias foo=`echo ! & rem`

C:\>foo
!

C:\>foo bar baz quux
!

C:\>
 
Last edited:
  • Like
Reactions: Alpengreis
So, I think an easy methode could be something like that (not changed the path real, just as example):

Code:
type SetPathTest.btm

@echo off

set PathToAdd=C:\

echo.

set SetPathVar=`C:\Windows;%PathToAdd;%*`

echo SetPathVar: %SetPathVar

unset PathToAdd
unset SetPathVar

Code:
SetPath.btm

SetPathVar: C:\Windows;C:\;


SetPath.btm Test

SetPathVar: C:\Windows;C:\;Test
 
"Very easy methode" is to never ever use "%*" - it is only included for compatibility with cmd and is nearly useless.
 

Similar threads