Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

for loop counter

2,260 views
Skip to first unread message

brzak

unread,
Oct 14, 2008, 12:07:32 AM10/14/08
to
hi,

i wanted to have a counter be incremented within a for loop (an
operation is performed on a group of files in a folder)

now, i found this: http://www.computing.net/answers/dos/batch-file-variables/14203.html
which seems to work fine...

@Echo Off

Set Count=1
:LOOP
Net Send * Hello
Set /A Count=%Count%+1
If %Count% lss 50 GoTo :LOOP

Echo Message sent %Count% times
Set Count=
Pause

running that does indeed produce the numbers 1 to 50, now i tried to
recreate this behaviour within a for loop, my attempt is:

@Echo Off
:: initialise counter
Set counter=1

:: for each file in the current directory
for %%f in (*.*) do (
:: increment counter (well taht is what is the aim anyway)
set /a counter=%counter%+1
::set /a counter+=1

:: write counter and filename to window
echo %counter% %%f
)


however, this produces a list of ones... enlightenment in this area
would be much appreciated!

thanks

Ted Davis

unread,
Oct 14, 2008, 12:29:01 AM10/14/08
to

Environment variables are expanded when the line is parsed - that means
%count% was evaluated only once ... before the FOR loop executed. YOu
have to use SETLOCAL or put the code that does things with the variable in
a subroutine.

for %%A in (*.*) do call :pass2
goto :cont
:pass2
set /a counter=%counter%+1
goto :EOF
:cont

However,
for /f %%A in ('dir *.* ^| find "File(s)"') do set count=%%A

Is simpler, and probably quicker.

--

T.E.D. (tda...@mst.edu) MST (Missouri University of Science and Technology)
used to be UMR (University of Missouri - Rolla).

billious

unread,
Oct 14, 2008, 1:15:42 AM10/14/08
to

"brzak" <brz...@gmail.com> wrote in message
news:a9043eb9-d373-4e6d...@m74g2000hsh.googlegroups.com...

Further to Ted's comment (and see Timo's FAQ - last posted on Oct 13th)

The "::" form of comment is a broken-label and is not allowed within a FOR
loop as labels aren't allowed in a for-loop.


brzak

unread,
Oct 14, 2008, 11:19:13 AM10/14/08
to


Ted,

that's great. I'm sure you're second example is a lot better but i'm
still learning the language so don't quite get what it's doing...
however, the first one is ok, though I have been warned to steer clear
of the goto (xkcd.com/292/)

thank you

brzak

unread,
Oct 14, 2008, 11:21:06 AM10/14/08
to

thanks for pointing out the FAQ, looks like there's alot of useful
stuff tehre - hours of fun!

didn't knnow about the problems "::" caused, i'll try to avoid in
future.

foxidrive

unread,
Oct 14, 2008, 11:43:33 AM10/14/08
to

To add to what the guys have said - enabledelayedexpansion gets around this
issue too, as long as an ! is not part of the text you are manipulating.

@Echo Off
setlocal enabledelayedexpansion
:: initialise counter
Set counter=0


:: for each file in the current directory
for %%f in (*.*) do (

REM increment counter
set /a counter+=1
REM write counter and filename to window
echo !counter! "%%f"
)
pause


Matthias Tacke

unread,
Oct 14, 2008, 2:00:10 PM10/14/08
to
brzak wrote:
> running that does indeed produce the numbers 1 to 50, now i tried to
> recreate this behaviour within a for loop, my attempt is:
>
just to show a different approach:

for /f "tokens=1,* delims=:" %%A in ('dir /B *^|findstr /N "."'
) do @echo %%A %%~fB


--
Regards
Matthias

Todd Vargo

unread,
Oct 14, 2008, 8:05:55 PM10/14/08
to
brzak wrote:
>
> ...I have been warned to steer clear of the goto (xkcd.com/292/)

As long as you can follow the program flow, there is nothing wrong with
using GOTO.

--
Todd Vargo
(Post questions to group only. Remove "z" to email personal messages)

Ted Davis

unread,
Oct 14, 2008, 8:28:31 PM10/14/08
to
On Tue, 14 Oct 2008 04:19:13 -0700, brzak wrote:

<snip>


>>
>> Environment variables are expanded when the line is parsed - that means
>> %count% was evaluated only once ... before the FOR loop executed.  YOu
>> have to use SETLOCAL or put the code that does things with the variable
>> in a subroutine.
>>
>>   for %%A in (*.*) do call :pass2
>>   goto :cont
>>   :pass2
>>   set /a counter=%counter%+1
>>   goto :EOF
>>   :cont
>>
>> However,
>>   for /f %%A in ('dir *.* ^| find "File(s)"') do set count=%%A
>>
>> Is simpler, and probably quicker.
>>
>> --
>>
>> T.E.D. (tda...@mst.edu) MST (Missouri University of Science and
>> Technology) used to be UMR (University of Missouri - Rolla).
>
>
> Ted,
>
> that's great. I'm sure you're second example is a lot better but i'm still
> learning the language so don't quite get what it's doing...

for /f %%A in ('dir *.* ^| find "File(s)"') do set count=%%A

Break it down into pieces:
DIR *.* ends with a report of the number of files and directories in the
listing - FIND isolates the single line containing the number of files;
FOR /f, without a "tokens=" argument will set the only variable to the
first field in each line, but since there is only one line getting through
FIND, %%A will never have any value except the first field in the files
report, which is the number - SET puts it in a variable. It is necessary
to escape certain characters when they occur inside the () of a FOR
command - "|" is one of them, and MS, unlike all sane OS providers, uses
"^" as its escape character. The single qoutes around the compound
command in the () tell FOR that the string *is* a command - double quotes
would indicate a string literal (to be broken into fields), and no quotes
at all mean that the string is a file name to be processed line by line
(the /f does that).

> however, the
> first one is ok, though I have been warned to steer clear of the goto
> (xkcd.com/292/)

The only way GOTO can be avoided there is to put the subroutine in a
separate file. It is necessary to jump over the subroutine unless you
*want* it to execute after the FOR is finished, and it is needed at the
endo of the subroutine unless the subroutine is at the end of the file in
order to implement a return (MS gave us CALL, but not its
necessary partner, RETURN). *Not* using GOTO where it is needed is a
common mistake. You may have been warned about using GOTO in structured
langauges, but that really doesn't apply in shell scripts and assembly
level programming where structure is almost nonexistant. It does have to
be used carefully.

--
T.E.D. (tda...@mst.edu)

Richard Bonner

unread,
Oct 14, 2008, 11:22:34 PM10/14/08
to
Todd Vargo (tlv...@sbcglobal.netz) wrote:
> brzak wrote:
> >
> > ...I have been warned to steer clear of the goto (xkcd.com/292/)

> As long as you can follow the program flow, there is nothing wrong with
> using GOTO.
> --
> Todd Vargo

*** I agree, Todd. I prefer it because it makes for cleaner code whereby
each operation is on a line by itself.

Richard Bonner
http://www.chebucto.ca/~ak621/DOS/

Richard Bonner

unread,
Oct 14, 2008, 11:36:52 PM10/14/08
to
Ted Davis (tda...@mst.edu) wrote:

> On Tue, 14 Oct 2008 04:19:13 -0700, brzak wrote:

> > ...I have been warned to steer clear of the goto

> The only way GOTO can be avoided there is to put the subroutine in a
> separate file. It is necessary to jump over the subroutine unless you
> *want* it to execute after the FOR is finished, and it is needed at the
> endo of the subroutine unless the subroutine is at the end of the file in
> order to implement a return (MS gave us CALL, but not its
> necessary partner, RETURN).

> --
> T.E.D. (tda...@mst.edu)

*** I could never understand why Microsoft was so slow to respond to
features added by other DOS manufacturers and by after-market utility
makers. "MOVE" is probably the most famous. "RETURN" has been available in
DR-DOS since at least the early 1990s, partnered with "GOSUB". 4DOS has
for some time offered both as well.

Richard Bonner
http://www.chebucto.ca/~ak621/DOS/

Andreas Eibach

unread,
Nov 5, 2008, 8:01:57 PM11/5/08
to

"Ted Davis" <tda...@mst.edu> schrieb im Newsbeitrag
news:pan.2008.10.14....@mst.edu...

> for %%A in (*.*) do call :pass2
> goto :cont
> :pass2
> set /a counter=%counter%+1
> goto :EOF
> :cont

Great solution.

> However,
> for /f %%A in ('dir *.* ^| find "File(s)"') do set count=%%A
>
> Is simpler, and probably quicker.

Hi,

and sorry for the very late answer.
However, I have to say the "probably quicker" solution is a solution I
cannot recommend, for it will be only working on _English_ DOS/Windows.

Let's say I need this to batch-control my own little tool, and I put this
under GPL.
How can I be sure every of my userbase will have English OS?

Your solution would require an extra solution for German locale
("Datei(en)"), French locale ("fichier(s)") and so on, and hence not be very
portable.

Regards,
Andreas

billious

unread,
Nov 6, 2008, 12:28:01 AM11/6/08
to

"Andreas Eibach" <aei...@mail.com> wrote in message
news:6nec1lF...@mid.uni-berlin.de...

Certainly. I believe that this is not a locale-independent solution.

Perhaps

for /f %%A in ('dir *.* ^| findstr "Datei(en)" "fichier(s)" "File(s)"') do
set count=%%A

would be closer - you'd simply need to add the key strings for extra
languages.

How about this? (and this problem seemed to go from a "numbered
filename-list" to a "count of files" problem - and there was a hint of "and
stop the loop after xx" as well...


This solution developed using XP
It may work for NT4/2K

----- batch begins -------
[1]@echo off
[2]:: solution to original "numbered list of files" problem
[3]for /f "tokens=1*delims=[]" %%i in ( ' dir /b /a-d ^|find /v /n "" ' ) do
echo %%i %%j
[4]echo ------------------------------------------
[5]:: solution to evolved "count of files" problem
[6]for /f %%i in ( ' dir /b /a-d ^|find /v /c "" ' ) do echo count=%%i
[7]echo ------------------------------------------
[8]:: solution to original "numbered list of files" problem with
justification
[9]setlocal enabledelayedexpansion
[10]for /f %%i in ( ' dir /b /a-d ^|find /v /c "" ' ) do set count=%%i
[11]set ycc=0
[12]:loop
[13]set /a count=%count%/10&set /a ycc+=1
[14]if not %count%==0 goto loop
[15]for /f "tokens=1*delims=[]" %%i in ( ' dir /b /a-d ^|find /v /n "" ' )
do (
[16]set yln= %%i
[17]echo !yln:~-%ycc%! %%j
[18])
------ batch ends --------

Lines start [number] - any lines not starting [number] have been wrapped and
should be rejoined. The [number] that starts the line should be removed

The ECHO keyword needs to be removed to activate the rename/delete It is
there as a safety measure to show what the process WOULD do until
you have verified that it will do what you require

The spaces surrounding the single-quotes are for emphasis only. The SPACES
are not required but the single-quotes ARE required.

%varname% will be evaluated as the value of VARNAME at the time that the
line is PARSED. The ENABLEDELAYEDEXPANSION option to SETLOCAL causes
!varname! to be evaluated as the CURRENT value of VARNAME - that is, as
modified by the operation of the FOR

This is an incomplete set of solutions. The last would only work on XP+(?)
as it uses the negative-offset characteristic which wasn't available in NT4.
Also, it doesn't take care of the situation where there are no (matching)
files in the directory and ignores the use of a filemask, both of which
should be relatively easy to implement - given the standard poison-character
problem.

Other than that, these should, I believe be universal.

Todd Vargo

unread,
Nov 7, 2008, 5:00:53 AM11/7/08
to
Andreas Eibach wrote:
> "Ted Davis" <tda...@mst.edu> schrieb im Newsbeitrag
> news:pan.2008.10.14....@mst.edu...
> > for %%A in (*.*) do call :pass2
> > goto :cont
> > :pass2
> > set /a counter=%counter%+1
> > goto :EOF
> > :cont
>
> Great solution.
>
> > However,
> > for /f %%A in ('dir *.* ^| find "File(s)"') do set count=%%A
> >
> > Is simpler, and probably quicker.
>
> Hi,
>
> and sorry for the very late answer.
> However, I have to say the "probably quicker" solution is a solution I
> cannot recommend, for it will be only working on _English_ DOS/Windows.

For personal usage this is not a problem. Simply set the string to your own
system's output.


>
> Let's say I need this to batch-control my own little tool, and I put this
> under GPL.
> How can I be sure every of my userbase will have English OS?

Batch files should not be used where an HLL is needed.


>
> Your solution would require an extra solution for German locale
> ("Datei(en)"), French locale ("fichier(s)") and so on, and hence not be
very
> portable.

The original thread was about counting in a loop, not language portability.
It is illogical to assume every solution posted should cater to the language
of every user/reader. Readers can take whatever solution may be offered and
modify them to suit their own needs or go on their own to create their own
solutions.

Dr J R Stockton

unread,
Nov 7, 2008, 5:41:59 PM11/7/08
to
In alt.msdos.batch message <6YPQk.6571$ZP4....@nlpi067.nbdc.sbc.com>,
Fri, 7 Nov 2008 00:00:53, Todd Vargo <tlv...@sbcglobal.netz> posted:

>
>The original thread was about counting in a loop, not language portability.
>It is illogical to assume every solution posted should cater to the language
>of every user/reader. Readers can take whatever solution may be offered and
>modify them to suit their own needs or go on their own to create their own
>solutions.

That's a very American position. Outside North America, many firms need
to work multi-lingually, and will want to be able to distribute their
batch files for use unmodified independently of localisations. Even in
North America, there are significant areas in which Spanish or French
are preferred to English.

The number of words that the OS is likely to give is not large.

It should be possible to distribute a small dictionary, which can be
interrogated by batch methods or otherwise to look up the local version
of a needed word. If such lookups are cached in the Environment, the
total overhead will not be great.

--
(c) John Stockton, nr London UK. ?@merlyn.demon.co.uk DOS 3.3 6.20 ; WinXP.
Web <URL:http://www.merlyn.demon.co.uk/> - FAQqish topics, acronyms & links.
PAS EXE TXT ZIP via <URL:http://www.merlyn.demon.co.uk/programs/00index.htm>
My DOS <URL:http://www.merlyn.demon.co.uk/batfiles.htm> - also batprogs.htm.

Todd Vargo

unread,
Nov 7, 2008, 9:55:53 PM11/7/08
to
Dr J R Stockton wrote:
> Todd Vargo posted:

> >
> >The original thread was about counting in a loop, not language
portability.
> >It is illogical to assume every solution posted should cater to the
language
> >of every user/reader. Readers can take whatever solution may be offered
and
> >modify them to suit their own needs or go on their own to create their
own
> >solutions.
>
> That's a very American position. Outside North America, many firms need
> to work multi-lingually, and will want to be able to distribute their
> batch files for use unmodified independently of localisations. Even in
> North America, there are significant areas in which Spanish or French
> are preferred to English.

Nonsense. IT professionals are paid for providing their firm with solutions,
not newsgroup participants. There is a major difference between an OP who
wants to learn and you third party posters who insist everyone be spoon fed.

>
> The number of words that the OS is likely to give is not large.
>
> It should be possible to distribute a small dictionary, which can be
> interrogated by batch methods or otherwise to look up the local version
> of a needed word. If such lookups are cached in the Environment, the
> total overhead will not be great.

Although that is achievable, I leave it to you to provide such solutions
whenever an OP requests one. That level of free assistance is beyond my
interest of participation these days.

0 new messages