Solved Loop with N iterations (& a counter) in DOS 7 batch file?

January 19, 2012 at 20:12:09
Specs: MSDOS 7.1
How can I increment a counter or do integer addition in a DOS 7.1 batch file?

I want to create a loop with N iterations that increments an integer input value and assigns an environment variable equal to this integer within each iteration. This integer would then be used in another command within each iteration.

Both N and the integer are command line inputs


See More: Loop with N iterations (& a counter) in DOS 7 batch file?

Report •


#1
January 20, 2012 at 09:00:17
try this

@echo off
set /p Ninput=What is the end value of the loop?
set /p Intinput=What is the starting value?
set /p EnvVar=What is the Env Var?
set /a count=%Intinput%
:loop
if %count% geq %Ninput% goto end
set %EnvVar%%count%=%count%
set /a count=%count% + 1
goto loop
:end
set %EnvVar%


Report •

#2
January 20, 2012 at 14:41:53
✔ Best Answer
I wrote a DOS increment script once (now lost ...). Here is my quick attempt to replicate it. It's not ideal in it's current state as it just writes scripts regardless if they exist and overwrites variables. I'm just posting this as an example.....

I didn't test this in DOS but I think it should be fine(no extended commands).

It will keep leading zeros if present.....

D:\home\bat>call add1.bat 20
D:\home\bat>echo %plus1%
21
D:\home\bat>call add1.bat 99
D:\home\bat>echo %plus1%
100

Now for the script itself:

@echo off
if "%1"=="" goto :end

rem __setnum.bat reverses the number and trims of excess
rem from the choice output string.
> __setnum.bat echo @echo off
>> __setnum.bat set incr=
>> __setnum.bat echo :loop
>> __setnum.bat echo shift
>> __setnum.bat echo set incr=%%1,%%incr%%
>> __setnum.bat echo if not "%%3"=="" goto loop


rem __incr.bat adds one using if
> __incr.bat echo @echo off
>> __incr.bat echo set done=
>> __incr.bat echo set plus1=
>> __incr.bat echo :loop
>> __incr.bat echo if "%%done%%"=="1" set plus1=%%1%%plus1%%
>> __incr.bat echo if not "%%done%%"=="1" if %%1==0 set plus1=1%%plus1%%
>> __incr.bat echo if %%1==0 set done=1
>> __incr.bat echo if not "%%done%%"=="1" if %%1==1 set plus1=2%%plus1%%
>> __incr.bat echo if %%1==1 set done=1
>> __incr.bat echo if not "%%done%%"=="1" if %%1==2 set plus1=3%%plus1%%
>> __incr.bat echo if %%1==2 set done=1
>> __incr.bat echo if not "%%done%%"=="1" if %%1==3 set plus1=4%%plus1%%
>> __incr.bat echo if %%1==3 set done=1
>> __incr.bat echo if not "%%done%%"=="1" if %%1==4 set plus1=5%%plus1%%
>> __incr.bat echo if %%1==4 set done=1
>> __incr.bat echo if not "%%done%%"=="1" if %%1==5 set plus1=6%%plus1%%
>> __incr.bat echo if %%1==5 set done=1
>> __incr.bat echo if not "%%done%%"=="1" if %%1==6 set plus1=7%%plus1%%
>> __incr.bat echo if %%1==6 set done=1
>> __incr.bat echo if not "%%done%%"=="1" if %%1==7 set plus1=8%%plus1%%
>> __incr.bat echo if %%1==7 set done=1
>> __incr.bat echo if not "%%done%%"=="1" if %%1==8 set plus1=9%%plus1%%
>> __incr.bat echo if %%1==8 set done=1
>> __incr.bat echo if not "%%done%%"=="1" if %%1==9 set plus1=0%%plus1%%
>> __incr.bat echo shift
>> __incr.bat echo if not "%%1"=="" goto loop
>> __incr.bat echo if "%%done%%"=="" set plus1=1%%plus1%%


rem choice splits the option string with commas
echo a|choice.com /c:a%1a __setnum.bat > __pass.bat
call __pass.bat
call __incr.bat %incr%

:end


Report •

#3
January 21, 2012 at 04:09:34
Quote:
"I wrote a DOS increment script once (now lost ...). Here is my quick attempt . . ."

That is a really GOOD answer in theory. ADD1.BAT worked right out of the box.
Running from the HDD the performance was acceptable as long as the number of
itteratiions is not too big. I would almost always want to, and possibly need to run
this from a floppy.

FYI: I am trying to create a batch file to use MBR Wizard to capture (or restore) a
range of sectors from my HDDs for recovey if needed (the MBR Wizard website and/or
"/?" help hints that it can do this, but in reality it can only get 1 sector at a time).
MBRWORK can capture a range interractively, but AFAIK this cannot be done from
the command line.

Quote:
"It's not ideal in it's current state as it . . ."

By this I think you mean at the beginning I should have tests like:

IF NOT '%DONE%'=='' GOTO ERRMSG1
IF EXIST __SETNUM.BAT GOTO ERRMSG2

and at the end I should clean things up like:

SET DONE=
DEL __SETNUM.BAT

Am I missing anything?

I have been playing with 4 possibilities demonstrated in the following batch file. All
have some serious problems. I'll discuss the pro's and con's of each (running from
floppy).

METHOD1 - FOR loop:
Pro's: This was really fast (about .02 sec per itteration). Minimal code to create the
loop.
Con's: Don't know how I could increment the LBA value in a FOR loop. Don't know if it
is possible to execute more than one command without the CALL statement. Calling a
bigger subroutine might slow it way down.
Comment: Seems like there ought to be a way to pick next digits out of a table. I'm
just not familiar enough with FOR to know what to do with this.

METHOD2 - Shareware XSET.EXE:
Pro's: Code is small and easy to write.
Con's: Performance is bad (about 9 sec per itteration). Built-in delays and occasional
pop-up messages telling me I should register. Big footprint (XSET.EXE is 59k). Will not
stay resident in memory - for this very reason, not sure if I would ever want to pay
for it.
Comment: A small TSR with just the XSET.EXE /MATH functionality would solve all my
problems.

METHOD3 - ADD1.BAT:
Pro's: Code is small and easy to write. Small footprint (CHOICE.COM is 6k).
Con's: Performance is really bad (about 49 sec per itteration). Constant reading and
writing to floppy. I don't know if a floppy drive could survive hours of non-stop reading
and writing. Lots of stuff needs to be cleaned up in the environment.
Comment: If there is a way to keep all the batch files resident in memory, the
itteration time should be reducable to a few miliseconds or microseconds.

METHOD4 - Math one digit at a time:
Pro's: Performance is adequate(about .85 sec per itteration; this improved to .57 sec
after a few runs; in one series of runs the time was about .015 sec - don't know
why?). No intense arm motion in the floppy drive, though it did seem to be reading
continuously.
Con's: Performance is marginal. Expanding the code to handle all situations could make
performance unnacceptable. As written, the carry digit is lost if the last 3 digits of the
LBA exceed 999. Code is easy to follow, but it is a voluminous monster, especially if I
want it to function for any number. Another block of similar code would be needed for
the loop counter if I want to avoid a CALL statement. Calling a subroutine might
greatly increase the itteration time. Digits have to be input individually.
Comment:If there is any way to parse strings in DOS 7, that would reduce the
complexity of this method considerably. If there is a way to keep this batch file
resident in memory, the performance issues would go away.

Here is a typical command line I used to run TEST.BAT (arguments are for last
method only):

TEST 144259 9 8 3 045

And here's the batch file TEST.BAT:

@echo off

rem print "00" thru "62" and pause thrice
REM This is really FAST, but needs a way to increment big number

ECHO @echo off        >  TESTSUB.BAT
ECHO echo %%1         >> TESTSUB.BAT
rem ECHO if %%1==20 pause }} TESTSUB.BAT
rem ECHO if %%1==40 pause }} TESTSUB.BAT

time
for %%i in (00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31) do call testsub %%i
for %%i in (32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62) do call testsub %%i
time
PAUSE

rem set typical big number
set LBA=144259920

rem print "0" thru "3" and LBA and pause using XSET.EXE
set count=0
:loop1
echo N=%count%   LBA=%lba%
if '%count%'=='3' GOTO END1
xset /math count = %count% + 1
xset /math lba   = %lba%   + 1
goto loop1
:END1
time
PAUSE


rem reset typical big number
set LBA=144259920

rem print "0" thru "2" and LBA using ADD1.BAT
set plus1=0
:loop2
echo N=%plus1%   LBA=%lba%
if '%plus1%'=='2' GOTO END2
call add1 %plus1%
set plus1tmp=%plus1%
call add1 %lba%
set lba=%plus1%
set plus1=%plus1tmp%
goto loop2
:END2
time


REM count using if (this can fail if ever NNLdigit=9)
REM cmdline: TEST BeginBig NNLdigit NLdigit Ldigit Last3Quit
set BeginBig=%1
set NNLdigit=%2
set NLdigit=%3
set Ldigit=%4
if '%BeginBig%'=='0' if '%NNLdigit%'=='0' if '%NLdigit%'=='0' set NLdigit=
if '%BeginBig%'=='0' if '%NNLdigit%'=='0'                     set NNLdigit=
if '%BeginBig%'=='0'                                          set BeginBig=
echo LBA=%BeginBig%%NNLdigit%%NLdigit%%Ldigit%

:LOOP3
set C1digit=
set C2digit=
set C3digit=

if '%Ldigit%'=='9' set C1digit=1
if '%Ldigit%'=='9' set Ldigit=0
if '%Ldigit%'=='8' set Ldigit=9
if '%Ldigit%'=='7' set Ldigit=8
if '%Ldigit%'=='6' set Ldigit=7
if '%Ldigit%'=='5' set Ldigit=6
if '%Ldigit%'=='4' set Ldigit=5
if '%Ldigit%'=='3' set Ldigit=4
if '%Ldigit%'=='2' set Ldigit=3
if '%Ldigit%'=='1' set Ldigit=2
if '%Ldigit%'=='0' if NOT '%C1digit%'=='1' set Ldigit=1

if '%C1digit%'=='1' if '%NLdigit%'=='9' set C2digit=1
if '%C1digit%'=='1' if '%NLdigit%'=='9' set NLdigit=0
if '%C1digit%'=='1' if '%NLdigit%'=='8' set NLdigit=9
if '%C1digit%'=='1' if '%NLdigit%'=='7' set NLdigit=8
if '%C1digit%'=='1' if '%NLdigit%'=='6' set NLdigit=7
if '%C1digit%'=='1' if '%NLdigit%'=='5' set NLdigit=6
if '%C1digit%'=='1' if '%NLdigit%'=='4' set NLdigit=5
if '%C1digit%'=='1' if '%NLdigit%'=='3' set NLdigit=4
if '%C1digit%'=='1' if '%NLdigit%'=='2' set NLdigit=3
if '%C1digit%'=='1' if '%NLdigit%'=='1' set NLdigit=2
if '%C1digit%'=='1' if '%NLdigit%'=='0' if NOT '%C2digit%'=='1' set NLdigit=1
if '%C1digit%'=='1' if '%NLdigit%'==''  set NLdigit=1

if '%C2digit%'=='1' if '%NNLdigit%'=='9' set C3digit=1
if '%C2digit%'=='1' if '%NNLdigit%'=='9' set NNLdigit=0
if '%C2digit%'=='1' if '%NNLdigit%'=='8' set NNLdigit=9
if '%C2digit%'=='1' if '%NNLdigit%'=='7' set NNLdigit=8
if '%C2digit%'=='1' if '%NNLdigit%'=='6' set NNLdigit=7
if '%C2digit%'=='1' if '%NNLdigit%'=='5' set NNLdigit=6
if '%C2digit%'=='1' if '%NNLdigit%'=='4' set NNLdigit=5
if '%C2digit%'=='1' if '%NNLdigit%'=='3' set NNLdigit=4
if '%C2digit%'=='1' if '%NNLdigit%'=='2' set NNLdigit=3
if '%C2digit%'=='1' if '%NNLdigit%'=='1' set NNLdigit=2
if '%C2digit%'=='1' if '%NNLdigit%'=='0' if NOT '%C3digit%'=='1' set NNLdigit=1
if '%C2digit%'=='1' if '%NNLdigit%'==''  set NNLdigit=1

echo LBA=%BeginBig%%NNLdigit%%NLdigit%%Ldigit%
if '%NNLdigit%%NLdigit%%Ldigit%'=='%5' goto QUIT
goto LOOP3

:QUIT
time


Report •

Related Solutions

#4
January 21, 2012 at 04:53:01
I don't really have an ideal solution, I just remembered that and thought it might be helpful.

By this I think you mean at the beginning I should have tests like:

Pretty much, also rewriting the auxiliary scripts. The only script that needed to be written at runtime was the "pass" script.

I don't know if a floppy drive could survive hours of non-stop reading
and writing.

Have you thought about a ramdisk? I can't help but think of the win98 boot floppy that had a compressed file for other utilities, a ramdisk creator and decompression tool. The archive was extracted to the ramdisk so after boot and copy there was not need for the floppy to even be present.

Other than that I'm afraid I can't be of much help.


Report •

#5
January 21, 2012 at 17:17:25
I don't really have an ideal solution, I just remembered that . . .

Well it is probably as close to ideal as possible without introducing a lot more into the mix. I wanted to do this in pure DOS, and your script delivers on that. Supplying the subscripts in advance instead of creating them on the fly should give a huge boost in performance. If not enough, I would be VERY surprised if putting all this stuff on a RAM disk did not solve the performance issues (I may even be able to keep ADD1.BAT self contained). Anyway, thanks for the script because I would not have come up with that on my own!

Pretty much, also rewriting the auxiliary scripts.

OK, I will do that, build in the safety measures, and post back the working scripts. So in practice, did you use it as a self contained package like you provided, or did you use the sub-scripts pre-made?


Report •

#6
January 21, 2012 at 18:29:55
Reducing ADD1.BAT to the following reduced my loop time to about 9 sec per itteration. A RAM drive will be essential.

@echo off
if "%1"=="" goto :end

>> __setnum.bat set incr=

rem choice splits the option string with commas
echo a|choice.com /c:a%1a __setnum.bat > __pass.bat
call __pass.bat
call __incr.bat %incr%

:end

Can you explain what the following line does, and if there was any significance in where it was placed within the ECHO's to __setnum.bat. I have not had any problem with the reduced script.

>> __setnum.bat set incr=


Report •

#7
January 21, 2012 at 19:43:38
Can you explain what the following line does

In the original context it added the line "set incr=" into "__setnum.bat".

"set incr=" was to clear the variable before use, this is very important because the variable isn't just set to, it is inserted to. If the variables aren't cleared then anything in the variable before execution comes along for the ride.

The position is important too, it is before the loop, that way it is cleared before any work starts, but is not cleared during the work.

As for the safety measures - Since it's just a boot disk your scripts are in control of the entire environment so this is minor. If you decide to split up the scripts you shouldn't even have to check for existence, if they don't exist the disk is probably corrupt which means bigger problems. One thing to watch out for is that the variables used(incr, plus1 and done) are overwritten in a persistent manner, so the important thing is not to use them for other purposes..

So in practice, did you use it as a self contained package like you provided, or did you use the sub-scripts pre-made?

I believe I used to use them separately to avoid the hit from constantly creating the files. The main reason I did it like that was so that I didn't have to try to explain how to name/create every script.


Report •

#8
January 21, 2012 at 21:16:50
Your explanation makes a lot of sense, which I think means you are telling me that this line should read:

>> __setnum.bat echo set incr=

which is what I thought when I first looked at it, but since everything was producing the right output, I thought I would leave well enough alone. I am just guessing, but I think the line:

>> __setnum.bat set incr=

is being interpreted as two separate commands: ">> __setnum.bat" (append nothing to __setnum.bat) and "set incr=". Anyway, I have tested it both ways and the results have been the same.


Report •

#9
January 21, 2012 at 23:28:05
You pointed it out and I still missed it!

Now I understand that it was missing echo, I just glazed over it ;)

The variable really should be cleared, especially because the script is going to be called multiple times. If you separate the scripts you might find that the fist use is fine and the second has problems.

It only works fine now because it is clearing the variable inside add1, with the null resulting output(nothing) being sent to file.


Report •

#10
January 25, 2012 at 13:39:45
"'So in practice, did you use it as a self contained package like you provided, or did you use the sub-scripts pre-made?'

I believe I used to use them separately to avoid the hit from constantly creating the files. The main reason I did it like that was so that I didn't have to try to explain how to name/create every script."

There ought to be a 'best of both worlds' and there is! I finished putting in some safety measures and an enhancement to keep it self contained. Also some notes about what you might want to clean up after done using it. Performance is only slightly worse than what I posted in reply #6 above. I tested it on a RAM drive and got loop times of less than 0.2 sec per itteration which is more than fast enough for what I want to do. My next task is to configure the RAM drive and the environment which can be found here: Configuring to Run Ghost 2003 from a RAM Drive .

Here is the revised script:

@echo off
::                  ADD1.BAT        Author: Judago

::   Increment positive integer by 1. Keeps leading zeroes if present.
::   Result is stored in environment variable "plus1"

::   This batch program requires CHOICE.COM in the current directory.

::   This batch program has been tested in MS-DOS v7.10.

::   Revised 2012/01/22: Added header, error messages, environment cleanup
::    by sburtchin     : and checks for existence of called batch files

::   NOTE: This batch program creates files "__setnum.bat" and "__incr.bat"
::         in the current directory.  These files and the environment variable
::         "plus1" may be deleted after use, or at the end of the batch program
::         which calls ADD1.BAT.

::             SYNTAX: ADD1 integer   or   call ADD1 integer


if "%1"=="" goto ERRMSG1
if NOT '%done%'=='' goto ERRMSG2
if NOT '%incr%'=='' goto ERRMSG3


if exist __setnum.bat goto havesetnumbat
rem __setnum.bat reverses the number and trims of excess
rem from the choice output string.
> __setnum.bat echo @echo off
>> __setnum.bat echo set incr=
>> __setnum.bat echo :loop
>> __setnum.bat echo shift
>> __setnum.bat echo set incr=%%1,%%incr%%
>> __setnum.bat echo if not "%%3"=="" goto loop
:havesetnumbat


if exist __incr.bat goto haveincrbat
rem __incr.bat adds one using if
> __incr.bat echo @echo off
>> __incr.bat echo set done=
>> __incr.bat echo set plus1=
>> __incr.bat echo :loop
>> __incr.bat echo if "%%done%%"=="1" set plus1=%%1%%plus1%%
>> __incr.bat echo if not "%%done%%"=="1" if %%1==0 set plus1=1%%plus1%%
>> __incr.bat echo if %%1==0 set done=1
>> __incr.bat echo if not "%%done%%"=="1" if %%1==1 set plus1=2%%plus1%%
>> __incr.bat echo if %%1==1 set done=1
>> __incr.bat echo if not "%%done%%"=="1" if %%1==2 set plus1=3%%plus1%%
>> __incr.bat echo if %%1==2 set done=1
>> __incr.bat echo if not "%%done%%"=="1" if %%1==3 set plus1=4%%plus1%%
>> __incr.bat echo if %%1==3 set done=1
>> __incr.bat echo if not "%%done%%"=="1" if %%1==4 set plus1=5%%plus1%%
>> __incr.bat echo if %%1==4 set done=1
>> __incr.bat echo if not "%%done%%"=="1" if %%1==5 set plus1=6%%plus1%%
>> __incr.bat echo if %%1==5 set done=1
>> __incr.bat echo if not "%%done%%"=="1" if %%1==6 set plus1=7%%plus1%%
>> __incr.bat echo if %%1==6 set done=1
>> __incr.bat echo if not "%%done%%"=="1" if %%1==7 set plus1=8%%plus1%%
>> __incr.bat echo if %%1==7 set done=1
>> __incr.bat echo if not "%%done%%"=="1" if %%1==8 set plus1=9%%plus1%%
>> __incr.bat echo if %%1==8 set done=1
>> __incr.bat echo if not "%%done%%"=="1" if %%1==9 set plus1=0%%plus1%%
>> __incr.bat echo shift
>> __incr.bat echo if not "%%1"=="" goto loop
>> __incr.bat echo if "%%done%%"=="" set plus1=1%%plus1%%
:haveincrbat


rem choice splits the option string with commas
echo a|choice.com /c:a%1a __setnum.bat > __pass.bat
call __pass.bat
call __incr.bat %incr%
goto end


:ERRMSG1
echo No input to ADD1.BAT - Hit Ctrl-C to terminate batch job and correct problem.
pause
goto end
:ERRMSG2
echo Environment variable "done" is about to be overwritten - Hit Ctrl-C to stop!
pause
goto end
:ERRMSG3
echo Environment variable "incr" is about to be overwritten - Hit Ctrl-C to stop!
pause
goto end


:end

del __pass.bat
set done=
set incr=

If there is anything you would change, please let me know.

Report •

#11
January 25, 2012 at 15:51:40
It looks good, I tried some optimising myself and made some changes, I'm not sure if it will be faster but it certainly looks cleaner.

• Removed the variables "done" and "incr". "plus1" is now used both as the temp and output variable.

• Made "__setnum.bat" call "__incr.bat" so only "__pass.bat" needs to be called in the main script.

• Converted the comments to help text and combined the one remaining error into the help.

• Changed the logic of adding to only loop the logic if a nine is passed through with other numbers remaining.

• Added a dummy character("q") to the reversed number to make a shift loop easier.

• Added "if exist" before deleting "__pass.bat"

• Removed a superfluous goto.

@echo off
if not "%1"=="" goto work
echo No input to ADD1.BAT - Hit Ctrl-C to terminate batch job and correct problem.
echo.
echo.                 ADD1.BAT        Author: Judago
echo.
echo.   Increment positive integer by 1. Keeps leading zeroes if present.
echo.   Result is stored in environment variable "plus1"
echo.
echo.   This batch program requires CHOICE.COM in the current directory.
echo.
echo.   This batch program has been tested in MS-DOS v7.10.
echo.
echo.   Revised 2012/01/22: Added header, error messages, environment cleanup
echo.    by sburtchin     : and checks for existence of called batch files
echo.
echo.   NOTE: This batch program creates files "__setnum.bat" and "__incr.bat"
echo.         in the current directory.  These files and the environment variable
echo.         "plus1" may be deleted after use, or at the end of the batch program
echo.         which calls ADD1.BAT.
echo.
echo.             SYNTAX: ADD1 integer   or   call ADD1 integer
echo.
goto :end


:work

if exist __setnum.bat goto havesetnumbat
rem __setnum.bat reverses the number and trims of excess
rem from the choice output string.
> __setnum.bat echo @echo off
>> __setnum.bat echo set plus1=
>> __setnum.bat echo :loop
>> __setnum.bat echo shift
>> __setnum.bat echo set plus1=%%1,%%plus1%%
>> __setnum.bat echo if not "%%3"=="" goto loop
>> __setnum.bat echo set plus1=q,%%plus1%%
>> __setnum.bat echo __incr.bat %%plus1%%

:havesetnumbat


if exist __incr.bat goto haveincrbat
rem __incr.bat adds one using if
> __incr.bat echo @echo off
>> __incr.bat echo set plus1=
>> __incr.bat echo :loop
>> __incr.bat echo shift
>> __incr.bat echo if %%1==0 set plus1=1%%plus1%%
>> __incr.bat echo if %%1==1 set plus1=2%%plus1%%
>> __incr.bat echo if %%1==2 set plus1=3%%plus1%%
>> __incr.bat echo if %%1==3 set plus1=4%%plus1%%
>> __incr.bat echo if %%1==4 set plus1=5%%plus1%%
>> __incr.bat echo if %%1==5 set plus1=6%%plus1%%
>> __incr.bat echo if %%1==6 set plus1=7%%plus1%%
>> __incr.bat echo if %%1==7 set plus1=8%%plus1%%
>> __incr.bat echo if %%1==8 set plus1=9%%plus1%%
>> __incr.bat echo if %%1==9 set plus1=0%%plus1%%
>> __incr.bat echo if %%1==9 if not "%%2"=="" goto loop
>> __incr.bat echo if %%1==9 set plus1=1%%plus1%%
>> __incr.bat echo :args
>> __incr.bat echo shift
>> __incr.bat echo set plus1=%%1%%plus1%%
>> __incr.bat echo if not "%%2"=="" goto args
:haveincrbat

rem choice splits the option string with commas
echo a|choice.com /c:a%1a __setnum.bat > __pass.bat
call __pass.bat


:end
if exist __pass.bat del __pass.bat > nul



Report •

#12
January 27, 2012 at 03:12:19
This has been a real learning experience for me. Thanks for returning the enthusiasm. I really like what you did to combine the header and help. I'm working on a batch file to run Ghost that has 5 screenfulls of help information. I can't say how many hours have been devoted to keeping the header and the help synchronized!

You cut the number of commands about in half, so I expected performance should almost double. Results were good, but a little surprising. I created a loop with counter and a large integer that is also incremented each time (ie. two calls to ADD1.BAT each time through the loop).

Here are the results of my testing (time per itteration):

                  Version1             Version2             Version3
Floppy          3 min 15 sec         2 min 10 sec         1 min 10 sec
Hard Drive        3.4 sec              1.2 sec              0.9 sec
RAM drive        0.12 sec             0.12 sec             0.12 sec

Recently I have begun to do version control on my batch files. Things were getting out of hand with assorted versions floating around on various floppies and HDD folders, so I created the directory "J:\Development_Projects\_DOS_BAT_File_Masters". Officially for my own records I created the files ADD1_v1.00.BAT, ADD1_v2.00.BAT and ADD1_v3.00.BAT in there. I also created a file ADD1.BAT.use.txt in there that lists the floppies (or other places) it is used, and any other important information that's not part of the header (eg. the url to this thread). The version information gets stripped from the filename to create the working batch program.

1> The file ADD1_v1.00.BAT is exactly as you provided in Reply #2 above with the exception that I corrected for the missing "echo".

2> I did some tweaks to the header info (in version 2) to make it compatible with the header in the final version, and also added help the way I had been doing it. The file ADD1_v2.00.BAT is the same as I posted in Reply #10 above except that it begins with:

@echo off

::                  ADD1.BAT        Author: Judago

::   Increment positive integer by 1. Keeps leading zeroes if present.
::   Result is returned in environment variable "plus1"

::   v1.00 2012/01/20 (Judago)    Initial Release.
::   v2.00 2012/01/22 (sburtchin) Added header, error messages, environment
::           cleanup and checks for existence of called batch files.  Added the
::           line "::+++...+++80___4" so you can always know where character
::           position "80" or "84" is at.  Added help.

::   This batch program requires CHOICE.COM in the current directory.

::   This batch program has been tested in MS-DOS v7.10.

::   NOTE: This batch program creates files "__setnum.bat" and "__incr.bat"
::         in the current directory.  These files and the environment variable
::         "plus1" may be deleted after use, or at the end of the batch program
::         which calls ADD1.BAT.

::     SYNTAX: ADD1 [/?³/h³/H]   or   ADD1 integer   or   call ADD1 integer

::++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++80___4
goto BEGIN

:help
echo:
echo                   ADD1.BAT        Author: Judago
echo:
echo   Increment positive integer by 1. Keeps leading zeroes if present.
echo   Result is stored in environment variable "plus1"
echo:
echo   v1.00 2012/01/20 (Judago)    Initial Release.
echo   v2.00 2012/01/22 (sburtchin) Added header, error messages, environment
echo           cleanup and checks for existence of called batch files.  Added the
echo           line "::+++...+++80___4" so you can always know where character
echo           position "80" or "84" is at.  Added help.
echo:
echo   This batch program requires CHOICE.COM in the current directory.
echo:
echo   This batch program has been tested in MS-DOS v7.10.
echo:
echo   NOTE: This batch program creates files "__setnum.bat" and "__incr.bat"
echo         in the current directory.  These files and the environment variable
echo         "plus1" may be deleted after use, or at the end of the batch program
echo         which calls ADD1.BAT.
echo:
echo     SYNTAX: ADD1 [/?³/h³/H]   or   ADD1 integer   or   call ADD1 integer
echo:
goto END

:BEGIN
if "%1"=="/?" goto help:
if "%1"=="/h" goto help:
if "%1"=="/H" goto help:

if "%1"=="" goto ERRMSG1

and ends with:

:end

del __pass.bat > nul
set done=
set incr=

with everything in the middle remaining the same.

3> The file ADD1_v3.00.BAT begins with the tweaked header (as follows) to be compatible with version 2, with everything else being the same as in your Reply #11 above.

@echo off
if not "%1"=="" goto work
echo No input to ADD1.BAT - Hit Ctrl-C to terminate batch job and correct problem.
echo.
:help
echo.
echo.                 ADD1.BAT        Author: Judago
echo.
echo.   Increment positive integer by 1. Keeps leading zeroes if present.
echo.   Result is returned in environment variable "plus1"
echo.
echo.   v1.00 2012/01/20 (Judago)    Initial Release.
echo.   v2.00 2012/01/22 (sburtchin) Added header, error messages, environment
echo.           cleanup and checks for existence of called batch files.  Added the
echo.           line "::+++...+++80___4" so you can always know where character
echo.           position "80" or "84" is at.  Added help.
echo.   v3.00 2012/01/25 (Judago)    Removed variables "done" and "incr". "plus1" is
echo.           now used both as the temp and output variable.  Made "__setnum.bat"
echo.           call "__incr.bat" so only "__pass.bat" is called in main script.
echo.           Converted comments to help text and combined the one remaining error
echo.           into the help.  Changed the logic of adding to only loop the logic
echo.           if a nine is passed through with other numbers remaining.  Added a
echo.           dummy character ("q") to the reversed number to make a shift loop
echo.           easier.  Added "if exist" before deleting "__pass.bat".  Removed a
echo.           superfluous goto.
pause
echo.
echo.   This batch program requires CHOICE.COM in the current directory.
echo.
echo.   This batch program has been tested in MS-DOS v7.10.
echo.
echo.   NOTE: This batch program creates files "__setnum.bat" and "__incr.bat"
echo.         in the current directory.  These files and the environment variable
echo.         "plus1" may be deleted after use, or at the end of the batch program
echo.         which calls ADD1.BAT.
echo.
echo.      SYNTAX: ADD1 [/?³/h³/H]   or   ADD1 integer   or   call ADD1 integer
echo.
::++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++80___4
goto :end


:work
if "%1"=="/?" goto help:
if "%1"=="/h" goto help:
if "%1"=="/H" goto help:


In case you are wondering, that is not the pipe character in the line:

echo.      SYNTAX: ADD1 [/?³/h³/H]   or   ADD1 integer   or   call ADD1 integer

Set font to "Terminal" in Notepad to see what it looks like in DOS.

Report •

#13
January 27, 2012 at 04:32:15
You cut the number of commands about in half, so I expected performance should almost double.

Yeah it isn't actually doing that much less work. Sometimes more code can even mean better performance, not often, but sometimes.

Results were good, but a little surprising.

I'm not very surprised that the ramdisk result is the same, a lot of that 0.12/sec is probably going to overhead with command filling argument buffers/switching contexts. That disk result is a little strange, my guess is that is may have something to to with a on disk write buffer that also reads....

Anyway I'm glad I could help and I hope you get that disk sorted ;)


Report •


Ask Question