1

So when I run this code:

@echo off
setlocal enabledelayedexpansion

set lstFolders= First Second 

set intCounter=0
for %%i in (!lstFolders!) do (
    set /a intCounter += 1
    set strFlder=%%i
    set strFolder!intCounter!=!strFlder!
    echo %%i
    echo !strFlder!
    echo !strFolder%intCounter%!
    echo !strFolder1!
    echo !strFolder2!
)

:End
pause
endlocal

It results with this:

First
First
ECHO is off.
First
ECHO is off.
Second
Second
ECHO is off.
First
Second

Why doesn't it allow me to echo the variable create with the format : !strFolder%intCounter%!? Is there another way to reference this variable and get the data that is inside of it?

mklement0
  • 382,024
  • 64
  • 607
  • 775
jrwygal
  • 27
  • 4
  • 1
    While not an exact duplicate, because _this_ question also asks about _creating_ variables indirectly (and is focused on using delayed evaluation), the following question is closely related: http://stackoverflow.com/q/9369874/45375 – mklement0 Aug 12 '16 at 04:32

2 Answers2

1

As @mklement0 already said, you need an extra evaluation step.
But inspite to use echo "%%strFolder!intCounter!%%", I would recommend delayed expansion.
As delayed expansion is immune to any content, echo "%%strFolder... will fail with content containing quotes or exclamation marks.

@echo off
setlocal enabledelayedexpansion

set "lstFolders=First Second"

set intCounter=0
for %%i in (!lstFolders!) do (
    set /a intCounter+= 1
    set "strFlder=%%i"
    set "strFolder!intCounter!=!strFlder!"
    echo !strFlder!
    set "varname=strFolder!intCounter!"
    for /F "delims=" %%A in (""!varname!"") do echo Indirect %%~A=!%%~A!
)

The doubling of the quotes avoids problems with the eol character of the FOR/F loop.

jeb
  • 78,592
  • 17
  • 171
  • 225
0

Caveat: The code below only works with list values (the tokens of %lstFolders% such as First) that:

  • contain neither spaces
  • nor any of the following chars.: & | < > "

A different looping approach would be needed to handle such cases.

@echo off
setlocal enabledelayedexpansion

set "lstFolders=First Second" 

set intCounter=0
for %%i in (%lstFolders%) do (
      rem Increment the counter
    set /a intCounter += 1
      rem Echo the loop variable
    echo #!intCounter!=%%i
      rem Set variable strFolder<intCounter> to the loop variable's value
    set "strFolder!intCounter!=%%i"
      rem Echo the variable created using variable indirection with for /f ('...')
    for /f "delims=" %%v in ('echo "%%strFolder!intCounter!%%"') do set "thisFolder=%%~v"
    echo %%thisFolder%% ^(via %%strFolder!intCounter!%%^)=!thisFolder!
)

Running the above yields:

#1=First
%thisFolder% (via %strFolder1%)=First
#2=Second
%thisFolder% (via %strFolder2%)=Second

What you're looking for is variable indirection:

  • While you can set a variable indirectly (by a name that you construct dynamically from the value of another variable), e.g.,
    • set "strFolder!intCounter!=%%i", with !intCounter! having a value of 1, correctly sets variable strFolder1 to the value of %%i),
  • you cannot get a variable's value that way; you need an extra evaluation step, which for /f ... ('echo ...') can provide.:

    • for /f "delims=" %%v in ('echo "%%strFolder!intCounter!%%"') do ... parses the output of the command in single quotes (echo ...) and assigns the result as a whole (delims=) to variable %%v
      (%%~v removes the enclosing double quotes, which were added around the echo argument to make the command handle shell metacharacters such as & | < > correctly).

    • %%strFolder!intCounter!%% immediately evaluates strFolder!intCounter! to strFolder1, if !intCounter! is 1, which, thanks to the enclosing doubled % instances, ends up as literal %strFolder1%, which is what the echo command sees when it is run by the for command, causing it to evaluate the variable reference and expand to its value.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 1
    Yes, I just put your code into a batch file and ran it, looked over it, and now i get it. Thank you so much, this is a huge help. – jrwygal Aug 12 '16 at 03:51