50

Can anyone explain this? I am able to count in a loop using the Windows command prompt, using this method:

SET /A XCOUNT=0
:loop
SET /A XCOUNT+=1
echo %XCOUNT%
IF "%XCOUNT%" == "4" (
  GOTO end
) ELSE (
  GOTO loop
)
:end

But this method does not work (it prints out "1" for each line in the file). It acts like the variable is out of scope:

SET /A COUNT=1
FOR /F "tokens=*" %%A IN (config.properties) DO (
  SET /A COUNT+=1
  ECHO %COUNT%
)

3 Answers 3

82

It's not working because the entire for loop (from the for to the final closing parenthesis, including the commands between those) is being evaluated when it's encountered, before it begins executing.

In other words, %count% is replaced with its value 1 before running the loop.

What you need is something like:

setlocal enableextensions enabledelayedexpansion
set /a count = 1
for /f "tokens=*" %%a in (config.properties) do (
  set /a count += 1
  echo !count!
)
endlocal

Delayed expansion using ! instead of % will give you the expected behaviour. See also here.


Also keep in mind that setlocal/endlocal actually limit scope of things changed inside so that they don't leak out. If you want to use count after the endlocal, you have to use a "trick" made possible by the very problem you're having:

endlocal && set count=%count%

Let's say count has become 7 within the inner scope. Because the entire command is interpreted before execution, it effectively becomes:

endlocal && set count=7

Then, when it's executed, the inner scope is closed off, returning count to it's original value. But, since the setting of count to seven happens in the outer scope, it's effectively leaking the information you need.

You can string together multiple sub-commands to leak as much information as you need:

endlocal && set count=%count% && set something_else=%something_else%
Sign up to request clarification or add additional context in comments.

4 Comments

wouldn't it work with only SETLOCAL ENABLEDELAYEDEXPANSION minus the ENABLEEXTENSIONS?
@Mechaflash: possibly, I've never tried. I always have that line at the top of my scripts since I use the other stuff as well.
Yeah, it turns out this was a BIG learning experience in the meaning of "enabledelayedexpansion" and what its uses are.
!count! was it! Thank you for explaining ! vs %!
27

for a = 1 to 100 step 1

Command line in Windows . Please use %%a if running in Batch file.

    for /L %a in (1,1,100) Do echo %a 

8 Comments

Your answer is not related to the question
this is the answer I was looking for when I searched for "counted for loop windows batch"
Me too -- this worked perfectly for me, and it's simple and elegant.
This answers exactly the question in the title. Next time, learn to summarize your question better ;)
for /L %a in (1,1,100) Do echo %a for pseudo for a = 1 to 100 step 1 is a poor example. A better one would be for /L %a in (1,5,100) Do echo %a for pseudo for a = 1 to 100 step 5 because it clearly implies syntax for /L %a in (start,step,end)
|
1

Here is a batch file that generates all 10.x.x.x addresses

@echo off

SET /A X=0
SET /A Y=0
SET /A Z=0

:loop
SET /A X+=1
echo 10.%X%.%Y%.%Z%
IF "%X%" == "256" (
 GOTO end
 ) ELSE (
 GOTO loop2
 GOTO loop
 )


:loop2
SET /A Y+=1
echo 10.%X%.%Y%.%Z%
IF "%Y%" == "256" (
  SET /A Y=0
  GOTO loop
  ) ELSE (
   GOTO loop3
   GOTO loop2
 )


:loop3

SET /A Z+=1
echo 10.%X%.%Y%.%Z%
IF "%Z%" == "255" (
  SET /A Z=0
  GOTO loop2
 ) ELSE (
   GOTO loop3
 )

:end

1 Comment

You can save the batch file and run it from the command line. You can then do a "ip.bat> ip.csv" at the command line and it will generate a csv of IP addresses.

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.