34

I have this for loop to get a list of directory names:

for /d %%g in (%windir%\Assembly\gac_msil\*policy*A.D*) do (
echo %%g
)

Output:

C:\WINDOWS\Assembly\gac_msil\policy.5.0.A.D
C:\WINDOWS\Assembly\gac_msil\policy.5.0.A.D.O
C:\WINDOWS\Assembly\gac_msil\policy.5.20.A.D.O
C:\WINDOWS\Assembly\gac_msil\policy.5.25.A.D.O
C:\WINDOWS\Assembly\gac_msil\policy.5.35.A.D.O
C:\WINDOWS\Assembly\gac_msil\policy.5.55.A.D.O
C:\WINDOWS\Assembly\gac_msil\policy.5.60.A.D.O
C:\WINDOWS\Assembly\gac_msil\policy.5.70.A.D.O
C:\WINDOWS\Assembly\gac_msil\policy.6.0.A.D.O

I want to get the folder names starting with "policy" but echo %%g:~29 doesn't work. I also tried to set x=%%g and then echo %x:~29% and still doesn't work.

So, how do I get substring from token in for loop?

Andre Silva
  • 4,782
  • 9
  • 52
  • 65
Ray Cheng
  • 12,230
  • 14
  • 74
  • 137

4 Answers4

52

Of course that set x=%%g and a substring extraction of x should work, but be aware that if the substring is taken inside a FOR loop, it must be done with ! instead of % (Delayed Expansion):

setlocal EnableDelayedExpansion
for /d %%g in (%windir%\Assembly\gac_msil\*policy*A.D*) do (
set x=%%g
echo !x:~29!
)
Aacini
  • 65,180
  • 12
  • 72
  • 108
  • useful tips here, thanks. Helped me write a script which I didn't think was possible. – Angst Mar 23 '16 at 19:03
  • 1
    @Aacini Is it possible to extract a substring directly from the parameter `%%g`, without using an auxiliary variable `x` and without enabling DelayedExpansion? – Alfredo Capobianchi May 30 '16 at 21:42
  • 1
    @AlfredoCapobianchi: Short answer: No. Long answer: if you carefully read the question, you should note this phrase: _"`echo %%g:~29` doesn't work"_. – Aacini May 31 '16 at 05:19
  • You saved my day also! The usage of setlocal EnableDelayedExpansion along "!" is what works inside a for loop – Rodrigo Caballero Apr 26 '17 at 23:08
9

On the other hand, if you want to know "How to get the last part (name and extension) of a token in for loop", the answer is: use the ~Name and ~eXtension modifiers in %%g replaceable parameter:

for /d %%g in (%windir%\Assembly\gac_msil\*policy*A.D*) do (
echo %%~NXg
)
Aacini
  • 65,180
  • 12
  • 72
  • 108
  • Thanks. I'm sure that'll come in handy someday. – Ray Cheng Dec 28 '11 at 18:31
  • Can you expand on how this actually works? I wanna do the same thing but I want all filenames (not just "policy" ones). I tried `*` and `\*.*` but it breaks on spaces and gives unexpected results. – laggingreflex Sep 04 '14 at 04:04
  • @RayCheng Wow, searched/experimented for a good hour or so regarding how to substring iterate-variables in a for loop. And then you show up and go all "oh and btw here is how you do it using 2 magic letters". This was exactly what i was looking for, thanks for saving my day :) – Jack Pettersson Apr 29 '15 at 14:00
2

I recently had a similar question, and I wanted to compile here the 3 working solutions:

  1. Use EnableDelayedExpansion in your batch file, as in the accepted answer

    @echo off
    setlocal EnableDelayedExpansion
    for /d %%g in (%windir%\Assembly\gac_msil\*) do (
     set x=%%g
     echo !x:~29!
    )
    
  2. Use for /f to process the output of a dir command

    for /f "tokens=*" %%g in ('dir /ad /b %windir%\Assembly\gac_msil\*') do @echo %%g
    
  3. And finally, the optimal solution in this case, using enhanced variable substitution. See the end of the help at for /? for more information on this syntax.

    for /d %%g in (%windir%\Assembly\gac_msil\*) do @echo %%~nxg
    
Jamesfo
  • 524
  • 6
  • 11
1

A simple

dir /B %windir%\Assembly\gac_msil\*policy*A.D*

should do the trick. If you want to loop over it:

for /f %%g in ('dir /B %windir%\Assembly\gac_msil\*policy*A.D*') do (
    echo %%g
)
ChrisWue
  • 18,612
  • 4
  • 58
  • 83
  • Neat! I'll use your suggestion but marked Aacini's as answer since that solution made me learn more. – Ray Cheng Dec 27 '11 at 19:33
  • Can you expand on how this actually works? I wanna do the same thing but I want all filenames (not just "policy" ones). I tried `*` and `\*.*` but it breaks on spaces and gives unexpected results. – laggingreflex Sep 04 '14 at 04:04
  • @laggingreflex: So you want `dir /B %windir%\Assembly\gac_msil\ ` - that should list all files in that directory? – ChrisWue Sep 08 '14 at 22:00