54

I created an array like this:

set sources[0]="\\sources\folder1\"
set sources[1]="\\sources\folder2\"
set sources[2]="\\sources\folder3\"
set sources[3]="\\sources\folder4\"

Now I want to iterate through this array:

for %%s in (%sources%) do echo %%s

It doesn't work! It seems that script is not going into the loop. Why is that? How can I iterate then?

aurel
  • 1,117
  • 2
  • 11
  • 24

6 Answers6

56

Another Alternative using defined and a loop that doesn't require delayed expansion:

set Arr[0]=apple
set Arr[1]=banana
set Arr[2]=cherry
set Arr[3]=donut

set "x=0"

:SymLoop
if defined Arr[%x%] (
    call echo %%Arr[%x%]%%
    set /a "x+=1"
    GOTO :SymLoop
)

Be sure you use "call echo" as echo won't work unless you have delayedexpansion and use ! instead of %%

Dss
  • 2,162
  • 1
  • 24
  • 27
42

If you don't know how many elements the array have (that seems is the case), you may use this method:

for /F "tokens=2 delims==" %%s in ('set sources[') do echo %%s

Note that the elements will be processed in alphabetical order, that is, if you have more than 9 (or 99, etc) elements, the index must have left zero(s) in elements 1..9 (or 1..99, etc.)

Bucket
  • 7,415
  • 9
  • 35
  • 45
Aacini
  • 65,180
  • 12
  • 72
  • 108
31

If you don't need environment variables, do:

for %%s in ("\\sources\folder1\" "\\sources\folder2\" "\\sources\folder3\" "\\sources\folder4\") do echo %%s
LS_ᴅᴇᴠ
  • 10,823
  • 1
  • 23
  • 46
  • 12
    This is definitely not helpful :/ I asked how to iterate through array, and you gave an answer: "just don't use the array!" – aurel Aug 28 '13 at 13:02
  • 24
    I only gave you this suggestion because sometimes I reconsider my program architecture depending on possible solutions. Imagine you had create array just to be able to iterate through items, then iterating without previous array would turn that array unneeded! – LS_ᴅᴇᴠ Aug 28 '13 at 13:12
  • notice that space between `in` and `(` is important. This wont work: `in("\\sources...)` but if you write with space `in ("\\sources...)` would work – Dimitry K Sep 04 '17 at 16:39
18

This is one way:

@echo off
set sources[0]="\\sources\folder1\"
set sources[1]="\\sources\folder2\"
set sources[2]="\\sources\folder3\"
set sources[3]="\\sources\folder4\"

for /L %%a in (0,1,3) do call echo %%sources[%%a]%%
foxidrive
  • 40,353
  • 10
  • 53
  • 68
5

For posterity: I just wanted to propose a slight modification on @dss otherwise great answer.

In the current structure the way that the DEFINED check is done causes unexpected output when you assign the value from Arr to a temporary variable inside the loop:

Example:

@echo off
set Arr[0]=apple
set Arr[1]=banana
set Arr[2]=cherry
set Arr[3]=donut

set "x=0"

:SymLoop
if defined Arr[%x%] (
    call set VAL=%%Arr[%x%]%%
    echo %VAL%
    REM do stuff with VAL
    set /a "x+=1"
    GOTO :SymLoop
)

This actually produces the following incorrect output

donut
apple
banana
cherry

The last element is printed first. To fix this it is simpler to invert the DEFINED check to have it jump over the loop when we're done with the array instead of executing it. Like so:

@echo off
set Arr[0]=apple
set Arr[1]=banana
set Arr[2]=cherry
set Arr[3]=donut

set "x=0"

:SymLoop
if not defined Arr[%x%] goto :endLoop
call set VAL=echo %%Arr[%x%]%%
echo %VAL%
REM do your stuff VAL
SET /a "x+=1"
GOTO :SymLoop

:endLoop
echo "Done"

This regardless of what you do inside the SymLoop always produces the desired correct output of

apple
banana
cherry
donut
"Done"
Sverrir Sigmundarson
  • 2,453
  • 31
  • 27
  • 1
    The problem in your first example is simply the `echo %var%` change it to `call echo %%var%%` and it works as expected. Or even better, use delayed expansion – jeb Dec 07 '18 at 09:50
  • @jeb This is the crux of the issue, the code inside the loop doesn't behave as you would expect it in a normal bat script. You need to call things differently. This will be a maintenance pain in the long term.. better just make sure it works as users expect. – Sverrir Sigmundarson Dec 07 '18 at 10:46
  • 1
    It behaves exactly as expected in a batch script! It's important to know, [how batch works](https://stackoverflow.com/a/4095133/463115), than to circumvent constructs you don't understand. And you couldn't circumvent all parenthesis blocks. – jeb Dec 07 '18 at 11:12
4

i use like this, what is important is that the variable is only 1 length, like %%a, and not like %%repo:

for %%r in ("https://github.com/patrikx3/gitlist" "https://github.com/patrikx3/gitter" "https://github.com/patrikx3/corifeus" "https://github.com/patrikx3/corifeus-builder" "https://github.com/patrikx3/gitlist-workspace" "https://github.com/patrikx3/onenote" "https://github.com/patrikx3/resume-web") do (
   echo %%r
   git clone --bare %%r
)
Patrik Laszlo
  • 4,906
  • 8
  • 24
  • 36