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"