# Wildcard expansion in FOR set

#### Christian Ullrich

The following line works in CMD, but not in TC (14.01.33):

Code:
for /d %a in ("%PROGRAMFILES%\app\version??") do set APPDIR=%a
The "app" in question has a subdirectory for every installed version, which ends in a two-digit version number. The above line is supposed to set %APPDIR% to the highest installed version.

In TC, the wildcards are not expanded. If I replace them with an existing version number, it works.

How do I do this in TC, or even better, is there a way to do it that will work in both CMD and TC?

#### rconn

Not reproducible here; TCC expands the wildcards as expected.

What do you see if you run:

for /d %a in ("%PROGRAMFILES%\app\version??") do echo %a

#### Christian Ullrich

No output at all.

#### Christian Ullrich

Uh, I may have simplified that example a little too much. You're right, it works with %PROGRAMFILES%. It does not work with %PROGRAMFILES(x86)%. (Yes, this is the x64 build of TC.)

#### rconn

TCC does not consider a '(' or ')' to be a valid variable name character, so it is terminating the name there. You can force TCC to accept the () characters either by using the %[...] syntax, or by forcing CMD-style variables (always require a trailing %) by setting "CMDVariables=Yes" in your TCMD.INI.

#### Christian Ullrich

This would really be the perfect solution; I don't really need the single-percent syntax, and the file would still run identically in TCC and CMD. Unfortunately, it does not work. There is no item in OPTION for that (as far as I can see), adding this line to tcmd.ini [4NT] manually does not affect (a newly started) TCC ("OPTION CMDVariables" => "CMDVariables=No"), and with the line there, TC (GUI) welcomes me with 'Error on line 122 of ...\TCMD.INI: Invalid item name "CMDVariables"'.

#### Frank

I have to draw back my post.
Something is not working as expected here.

#### Christian Ullrich

Note to self: Next time, make sure to put the option in the section it's meant to go. I did not notice the [TakeCommand] section header ...

Sorry for the useless noise.

#### Steve Fabian

Note to self: Next time, make sure to put the option in the section it's meant to go ...
You can guarantee it by the syntax below:

%@iniwrite[%@quote[%_ininame],section,directive,value]

which also guarantees that it will be written into the .INI file actually used by TCC.

#### jwiede

I'm seeing something which looks vaguely similar. Given the sequence:

for /f "tokens=3 delims=.]" %%i in ('%~dp0x86\foo.exe -v') do set _NUMBER=%%i​
and foo.exe which returns output in format "Title [Buildcode 00.00.0000]", I want %i to wind up containing the third value of the buildcode value (e.g. '0000'). When I run the exact same sequence in cmd.exe, that is precisely what happens. However, running it in TCC.EXE what I actually get is an error, 'TCC: Unknown command "\foo.exe" ' instead.

If I replace '%~dp0x86\foo.exe -v' with 'c:\scripts\x86\foo.exe -v' (removing the need for expansion) the sequence works as expected. Unfortunately, the script I'm really concerned with uses that type of sequence all over the place, so removing all the needs for expansion isn't practical.

Any idea what's going on with this? It definitely seems like something is broken w.r.t. symbol expansion in certain FOR syntaxes.

Thanks!

#### rconn

I'm seeing something which looks vaguely similar. Given the sequence:

for /f "tokens=3 delims=.]" %%i in ('%~dp0x86\foo.exe -v') do set _NUMBER=%%i​
and foo.exe which returns output in format "Title [Buildcode 00.00.0000]", I want %i to wind up containing the third value of the buildcode value (e.g. '0000'). When I run the exact same sequence in cmd.exe, that is precisely what happens. However, running it in TCC.EXE what I actually get is an error, 'TCC: Unknown command "\foo.exe" ' instead.
TCC isn't expanding the %~dp0 construct because "0" isn't a valid FOR variable. According to the Microsoft documentation, it isn't valid in CMD either -- what do you expect it to be returning? (And where in the Windows documentation is this mentioned?)

#### jwiede

Sorry, it's not that clear with the forum font, but that's %~dp(zero) not %~dp(letter o). The %~dp0 is a valid variable, pulling the drive and filepath from the current script that's executing.

#### vefatica

Sorry, it's not that clear with the forum font, but that's %~dp(zero) not %~dp(letter o). The %~dp0 is a valid variable, pulling the drive and filepath from the current script that's executing.
Rex had it right (the zero, that is). And it does seem to be a valid variable name in CMD.
Code:
Microsoft Windows [Version 6.1.7601]

v:\> set ~dp0x86=foo

v:\> echo %~dp0x86%
foo

v:\>
But not in TCC.
Code:
v:\> ver

TCC  14.02.36  Windows 7 [Version 6.1.7601]

v:\> set ~dp0x86=foo

v:\> echo %~dp0x86
ECHO is OFF

#### jwiede

Normally the tilde expansions are only valid when called from within an executing script. The tilde expansion allows for formatted access to the executing script's command line. The d subtoken indicates drive, the p subtoken indicates filepath, the zero indicates the zeroth cmd line arg (e.g. the name of the script itself).

So if a script file "G:\foo\bar.bat" is executing, references to %~dp0 will be expanded to "G:\foo\" (sans quotes of course). This appears to work normally in both cmd.exe and tcc.exe scripts as expected, except for the odd case inside the 'FOR /F' command in tcc.exe where it isn't being properly expanded/replaced.

#### samintz

##### Scott Mintz
This working perfectly fine for me.
foo.bat:
Code:
@echo on
setlocal
echo 'call %~dp0x86\foobar.bat -v'
for /f "tokens=3 delims=.]" %%i in ('call %~dp0x86\foobar.bat -v') do set _NUMBER=%%i
echo %_NUMBER
endlocal
I created an x86 subdirectory and put foobar.bat there:
Code:
echo Title [Buildcode 00.00.0000]
And I get this result:
Code:
[C:\CCViews] foo
setlocal
echo 'call C:\CCViews\x86\foobar.bat -v'
'call C:\CCViews\x86\foobar.bat -v'
for /f "tokens=3 delims=.]" %%i in ('call %~dp0x86\foobar.bat -v') do set _NUMBER=%%i
echo 0000
0000
endlocal
Is this a CMD compatibility setting? I have both "Duplicate CMD.EXE bugs" and "CMD.EXE delayed expansion (!var!)" turned ON.

-Scott

#### vefatica

I figured the '~' notation might have something to do with CMD's weird variable substitution, but found no mention of "~dp..." in the help for SET (in Win7's CMD). Where is that documented (in Windows)? Is it documented anywhere in TCC?

#### samintz

##### Scott Mintz
Vince,
It is documented under FOR and CALL.
Code:
cmd /c for /?
cmd /c call /?
-Scott

#### vefatica

Vince,
It is documented under FOR and CALL.
Code:
cmd /c for /?
cmd /c call /?
-Scott
Thanks, Scott. I see. And, according to your example, TCC has no problem telling that the variable ends at the '0' (and doesn't include the "x86"). That's good. As I said before, TCC has a problem with ordinary variables with such names. It'll set them but not de-reference them.
Code:
v:\> ver

TCC  14.02.36  Windows 7 [Version 6.1.7601]

v:\> set ~dp1=foo

v:\> set ~*
~dp1=foo

v:\> echo %~dp1
ECHO is OFF

#### jwiede

Is this a CMD compatibility setting? I have both "Duplicate CMD.EXE bugs" and "CMD.EXE delayed expansion (!var!)" turned ON.
Interesting, I'll give those a try and see if either makes a difference. I'm not at work, so don't recall their settings now, but will try each and/or both and see if the scripts in question start working.

As for tcc.exe not expanding per vefatica's comment, is that a bug then, and if so, is JPSoft able to reproduce and such can we expect a fix?

Thanks!

#### jwiede

Okay, just checked and while I had both "Duplicate CMD.EXE bugs" and "CMD.EXE delayed expansion" enabled, yet I'm not seeing the expected expansion here. I'm running the 64-bit version of TCC, running on W7SP1 Enterprise (if it matters).

What I'd really like to know is whether anyone at JPSoft can replicate this expansion problem in FOR /F?

#### rconn

Sorry, it's not that clear with the forum font, but that's %~dp(zero) not %~dp(letter o). The %~dp0 is a valid variable, pulling the drive and filepath from the current script that's executing.
No, it's really not a valid variable, because:

1) It's (as far as I can tell) completely undocumented, and
2) If it was really a valid variable, then the construct %~0 would also work in CMD (it doesn't), and
3) No other batch argument (i.e., %~dp1) works

So CMD is considering %~..0 to be a (undocumented) special case (either deliberately or inadvertently). I could add a (nasty) kludge to TCC to emulate that, but I'm not convinced that it's a "feature" and not a "bug".

#### vefatica

It is documented (CALL /?); the "1" is just a placeholder.

Code:
%~dp1      - expands %1 to a drive letter and path only
And it works in CMD.

Code:
v:\> cmd
Microsoft Windows [Version 6.1.7601]

v:\> type  dp.bat
echo %~dp0
echo %~dp1

v:\> dp.bat q:\garbage

v:\> echo v:\
v:\

v:\> echo q:\
q:\

v:\>

#### JohnQSmith

1) It's (as far as I can tell) completely undocumented
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/batch.mspx?mfr=true
Then click "Using batch parameters".

So CMD is considering %~..0 to be a (undocumented) special case (either deliberately or inadvertently).
Third sentence from that page...

Microsoft said:
When you use batch parameters in a batch file, %0 is replaced by the batch file name, and %1 through %9 are replaced by the corresponding arguments that you type at the command line.

#### Charles Dye

##### Super Moderator
It is documented (CALL /?); the "1" is just a placeholder.

Code:
%~dp1      - expands %1 to a drive letter and path only
And it works in CMD.

Code:
v:\> cmd
Microsoft Windows [Version 6.1.7601]

v:\> type  dp.bat
echo %~dp0
echo %~dp1

v:\> dp.bat q:\garbage

v:\> echo v:\
v:\

v:\> echo q:\
q:\

v:\>
And by an odd coincidence, it also works in TCC:

Code:
C:\>ver

TCC  14.02.36  Windows XP [Version 5.1.2600]

C:\>type dp.bat
@echo off
echo %~dp0
echo %~dp1

C:\>dp.bat q:\garbage
C:\
q:\

C:\>
Rex, I think you must be repressing the memory as intolerable psychological trauma -- but you really did re-engineer this CMD.EXE horror!

#### JohnQSmith

And by an odd coincidence, it also works in TCC:
...
Rex, I think you must be repressing the memory as intolerable psychological trauma -- but you really did re-engineer this CMD.EXE horror!
Yeah, works for me too.
Here's CMD
Code:
C:\temp>type dp.bat
@echo off
echo f - %~f0
echo dpnx - %~dpnx0

C:\temp>dp
f - C:\temp\dp.bat
dpnx - C:\temp\dp.bat
and here's TCC
Code:
[C:\temp]
10:02:29 \$ dp
f - C:\temp\dp.bat
dpnx - C:\temp\dp.bat