56

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?

6 Answers 6

58

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 %%

Sign up to request clarification or add additional context in comments.

2 Comments

I like this way. Its bit simpler
Whoever designed loops syntax in batch files was... a funny guy.
43

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.)

Comments

32

If you don't need environment variables, do:

for %%s in ("\\sources\folder1\" "\\sources\folder2\" "\\sources\folder3\" "\\sources\folder4\") do echo %%s

3 Comments

This is definitely not helpful :/ I asked how to iterate through array, and you gave an answer: "just don't use the array!"
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!
notice that space between in and ( is important. This wont work: in("\\sources...) but if you write with space in ("\\sources...) would work
19

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]%%

4 Comments

@LS_dev Oh ye of little faith. Try it. :)
You're right, my apologies! As an aside, it would be nice to have a dynamic iteration regardless of array length.
note that the for /L loop needs (0,1,<last_element_id>), in this case last_element_id is 3
Note: it does not work without the "call" command
8

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"

5 Comments

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 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.
It behaves exactly as expected in a batch script! It's important to know, how batch works, than to circumvent constructs you don't understand. And you couldn't circumvent all parenthesis blocks.
The line call set VAL=echo %%Arr[%x%]%% didnt work for me until i removed the echo. Otherwise the "echo" was kept as part of VAL
Same as @Plater, I had to remove the echo from echo %%Arr[%x%]%% and it worked beautifully (using windows 10 with .bat file)
5

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
)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.