0

Okay. I got rid of most of the useless code and have been tinkering with it here and there trying to find what is the problem and I think I finally found it:

Windows' Batch can't edit variables that will be expanded if those are inside a FOR loop.

Ex:

set /a x=1
Powershell Get-Clipboard> %temp%\ffmpeglist.txt
setlocal enableExtensions enableDelayedExpansion
for /F "delims=| tokens=*" %%A in (%temp%\ffmpeglist.txt) do (
    set input[!x!]=%%A
    call echo !input[%x%]!
    set /a x += 1
)
endlocal

Expected behavior:

g:\videos\youtube1.mp4
g:\videos\youtube2.mp4
g:\videos\youtube3.mp4
g:\videos\youtube4.mp4
g:\videos\youtube5.mp4

What I get:

g:\videos\youtube1.mp4
g:\videos\youtube1.mp4
g:\videos\youtube1.mp4
g:\videos\youtube1.mp4
g:\videos\youtube1.mp4

No matter what I do, set /a x+= 1 will not change the value of x.

Are there solutions? I'm open to anything.

HASJ
  • 57
  • 7
  • Is this all the code you have on hand? You may be experiencing the delayed-expansion issue. –  May 05 '18 at 00:28
  • I'll edit in the entire code. – HASJ May 05 '18 at 00:32
  • I can't believe this. Delayed Expansion does not work in FOR loops... Thanks @SteveFest – HASJ May 05 '18 at 00:47
  • Delayed expansion works in for loop, but not everywhere in a for loop. –  May 05 '18 at 00:48
  • You do not need delayed expansion everywhere, simply set it is the areas where you do need it and disable where you don't. – Gerhard May 05 '18 at 06:15
  • So the question has fundamentally changed. Please take a look. – HASJ May 06 '18 at 01:07
  • I suggest you to read [this answer](https://stackoverflow.com/questions/10166386/arrays-linked-lists-and-other-data-structures-in-cmd-exe-batch-script/10167990#10167990), that includes this explanation: _To get the value of an element when the index changes inside FOR/IF, enclose the element in double percent symbols and precede the command with call. Another way to achieve the previous process is to use an additional FOR command to change the delayed expansion of the index by an equivalent replaceable parameter, and then use the delayed expansion for the array element._ – Aacini May 06 '18 at 02:11
  • You're a damn genius @Aacini , you know that? – HASJ May 06 '18 at 10:50

2 Answers2

1

EDIT

In your heavily changed batch (in fact a new question) change

 call echo !input[%x%]!

to

 call echo %%input[!x!]%%

If in a (code block) you might need delayed expansion to force actual values, if at the same time using an indexed variable you need another level of delayed expansion you can accomplish with a pseudo call and doubled percent signs

Call set Input=%%input[!x!]%%
mediainfo --Output=Video;%%Height%% !input! > %temp%\ffmpegres%x%.txt
  • I have managed to fix that part of the program. The issue now is how to alter the variable/index INSIDE the `FOR` loop. Any ideas? – HASJ May 06 '18 at 01:10
  • I see! So `CALL` executes the command from outside the `FOR` loop? – HASJ May 06 '18 at 11:00
  • 1
    No, the call forces a second evaluation of the line through the parser, in the first pass the double %% were reduced to one and the current value for !x! inserted. In the second pass then `%input[1]%` (or any following number) gets evaluated. –  May 06 '18 at 11:20
  • Then it is a delayed expansion that has been delayed? – HASJ May 06 '18 at 11:47
  • Not exactly, because inside a (code block) the `!x!` was required and worked, to get a another different delayed expansion the call was used. It doesn't work with all commands - set/echo do an if for example does not. –  May 06 '18 at 11:52
0

Thanks to @Aacini and @LotPings , I've arrived at the answer:

set /a x=1
Powershell Get-Clipboard> %temp%\ffmpeglist.txt
setlocal enableDelayedExpansion
for /f "delims=|" %%A in (%temp%\ffmpeglist.txt) do (
    set input[!x!]="%%A"
    for %%i in (!x!) do echo !input[%%i]!
    set /a x =+ 1
)

The problem wasn't that BATCH couldn't

edit variables that will be expanded if those are inside a FOR loop.

But that it does it in a not very straight forward way.

HASJ
  • 57
  • 7
  • Excuse me, but your conclusion is wrong. The only problem with your original code is change the `call echo !input[%x%]!` line by `call echo %%input[!x!]%%` or by `for %%x in (!x!) do echo !input[%%x]!` as described in [my comment](https://stackoverflow.com/questions/50184403/how-to-count-arrays-in-for-loops-using-a-variable-as-index#comment87408350_50184403). Your original `set /a x += 1` line is correct and it not needs any change... Perhaps you misread _and then use the delayed expansion for the **array element**_ (not for the index). **`:/`** – Aacini May 06 '18 at 13:24
  • I got my definitions wrong. I was referring to **array element** as variables still. – HASJ May 06 '18 at 15:31
  • Again. These two lines are not needed: `set /a j=x + 1` and `for %%j in (!j!) do set x=%%j`. This line achieve the same thing: `set /a x += 1`. In these lines `x` is the _index variable_ (not an **array element**), and the `call %%` or `for` methods explained before are needed just to access array elements (not to increment a simple variable)... – Aacini May 06 '18 at 16:13
  • I can't believe it. I was doing the `set /a x += 1` command as `set /a x=x += 1` and that's why I needed those two extra lines. I'm so dumb. – HASJ May 06 '18 at 17:08
  • I don't follow you; your posted code have this line: `set /a x += 1`. Anyway, IMHO this whole answer has no sense and should be deleted... – Aacini May 07 '18 at 01:42