(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
Jan 12, 2014
520
11
Switzerland, SO
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:
Jan 12, 2014
520
11
Switzerland, SO
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:

Charles Dye

Super Moderator
Staff member
May 20, 2008
4,689
106
Albuquerque, NM
prospero.unm.edu
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
 

Charles Dye

Super Moderator
Staff member
May 20, 2008
4,689
106
Albuquerque, NM
prospero.unm.edu
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
Jan 12, 2014
520
11
Switzerland, SO
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
 
Aug 23, 2010
688
9
"Very easy methode" is to never ever use "%*" - it is only included for compatibility with cmd and is nearly useless.
 

Similar threads