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
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).
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.
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
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.
@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
for /f "tokens=1,* delims=:" %%A in ('dir /B *^|findstr /N "."'
) do @echo %%A %%~fB
--
Regards
Matthias
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)
<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)
> 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/
> 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/
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
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.
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.
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.
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.