0

I wrote the following batch file:

setlocal EnableDelayedExpansion
set integer=0
for /f "delims=" %%a in ('where /R C:\ /F python.exe') do (
    set Paths[!integer!]=%%a
    set /A integer+=1
)

for %%b in (%Paths%) do (
    echo %%b
)

The idea is that I want to run where /R C:\ /F python.exe and then store the several paths outputted into an array, I need this because I need to handle these paths later on. So far for testing purposes I called the second half of the script just to make sure the array is working properly.

Hadi Farah
  • 1,091
  • 2
  • 9
  • 27
  • 1
    `set Paths[` would display the stored paths... So you expect the second part to return the stored paths? This cannot work, because ther are no real arrays in batch; there are just normal variables with names like `Paths[0]`, `Paths[1]`, etc., whose names appear like arrays... See also this post: [Arrays, linked lists and other data structures in cmd.exe (batch) script](https://stackoverflow.com/a/10167990). – aschipfl Jul 05 '18 at 14:13
  • ok I see, then I need to know previously how many paths I have and loop over intergers and call `for /L %%i in (0,1,3..) do (echo !vector[%%i]!)`. Or maybe by incrementing `interger` I can use `for /L %%i in (0,1,%integer%)` – Hadi Farah Jul 05 '18 at 14:19
  • 3
    Yes. After the first part, do `set /A count=integer-1` to get the last index, then do `for /L %%i in (0,1,%count%) do echo !Paths[%%i]!`. Alternatively, you could do `for /F "tokens=1* delims==" %%i in ('set Paths[ 2^> nul') do echo %%i: %%j` (but this does not return sorted items as soon as there appear indexes woth more than one digit due to alphabetic sorting of `set Paths[`). – aschipfl Jul 05 '18 at 14:23
  • @aschipfl yes, it seems I have 12 Paths, but the first format works fine! – Hadi Farah Jul 05 '18 at 14:42
  • 2
    ... alternatively, you could increment `set /A integer+=1` _before_ `set Paths[!integer!]=%%a` and at end, do the `for /L` from `1` to `%integer%`... – Aacini Jul 05 '18 at 15:05
  • thank you for your quick responses and help! – Hadi Farah Jul 05 '18 at 15:07
  • 1
    @Aacini, that's somehow a matter of taste whether you prefer base-0 or base-1 arrays; though I have to admit, in batch base-1 arrays seem to be slightly easier to handle sometimes... – aschipfl Jul 05 '18 at 15:19

1 Answers1

1

Your second part is wrong. Since there are no real arrays in batch scripting, you cannot use a for loop similar to something like for each element in array do as used in other languages. Refer to this post for details: Arrays, linked lists and other data structures in cmd.exe (batch) script.

To loop through all (pseudo-)array elements you could do the following instead:

set /A count=integer-1
for /L %%i in (0,1,%count%) do echo Paths[%%i] = !Paths[%%i]!

As suggested by Aacini in a comment, you might change your base-0 to a base-1 (pseudo-)array by moving the line set /A integer+=1 upwards to be before line set Paths[!integer!]=%%a in your first part, so the variable integer already contains the greatest index, which would lead to a slightly simpler second part:

for /L %%i in (1,1,%integer%) do echo Paths[%%i] = !Paths[%%i]!

Alternatively, you could use a for /F loop that parses the output of set Paths[:

for /F "tokens=1* delims==" %%i in ('set Paths[ 2^> nul') do echo %%i = %%j

This might be beneficial:

  • you do not need to know the total number of elements;
  • the indexes do not have to be adjacent, they could even be non-numeric;

But there are two caveats:

  • the (pseudo-)array elements are not returned in ascending order with respect to the indexes, because set Paths[ returns them alphabetically sorted, where the order is 0, 1, 10, 11,..., 2, etc., so the order becomes jumbled as soon as there are indexes with more than a single digit;
  • in case there exist other variables beginning with that name, like Paths[invalid] or Paths[none, they become returned too;
aschipfl
  • 33,626
  • 12
  • 54
  • 99