40
votes

I've spent the past 3hrs trying to work this out but just couldn't find a solution. Here's my batch script:

if NOT Exist Counter.txt GOTO START
Type c:\counter.txt
if %COUNTER% EQU %Cycles% goto Pass
if NOT %COUNTER% EQU %Cycles% goto Cycle

:START
Set COUNTER=0
set CYCLES=250

:Cycle
set /A COUNTER=%COUNTER%+1     <----------- PROBLEM
echo Iteration %COUNTER% of %CYCLES%
echo Delay 3 seconds to reboot
choice /cy /n /t:y,3
warmboot.com

:Pass
pause

What it's doing is it runs the file "warmboot.com" (which reboots my PC) and runs for 250 cycles. Once the cycles have run 250 times (i.e when counter equals cycles) then it stops.

Under Windows, this works. However, this doesn't work under DOS environment. I've tried versions from v4 all the way up to v6.22 and even v7 and they all fail when it reaches the "PROBLEM" line.

If I do this:

set /A COUNTER=%COUNTER%+1
echo %Counter%

OR this:

set /A COUNTER+=1
echo %Counter%

both will return a blank line, i.e it shows nothing as the output.

If I type:

set /?

then it shows this:

Displays, sets, or removes cmd.exe environment variables.

SET [variable=[string]]

variable Specifies the environment-variable name.
string Specifies a series of characters to assign to the variable.

but typing the same command under CMD in Windows shows a lot more stuff. I'm thinking that the SET function under DOS doesn't support arithmetic functions, but for work purposes I have to run my scripts in DOS only.

Any ideas?

9
I'm pretty sure plain DOS can't do this. Write an actual program instead (there are plenty of languages to choose from, e.g. Turbo Pascal or C, maybe even QBasic).Michael Madsen
@Michael Madsen, I'm unfamiliar with those languages and for my job requirements I have to run the batch script in DOS.shadowz1337
Good old times... Wasn't there a BASIC delivered with DOS? If I remember correctly, it was only one EXE, and it was quite small (below 1 MB?)Stephan
@shadowz1337: Does your job requirements explicitly state it has to be a batch script, or just that it has to run in DOS? All of the compilers/languages I mention run in plain 16-bit DOS, and there is very little to learn in order to make a program like this.Michael Madsen
lines 1 and 2 will work in MSDos. Lines 3 and 4 will give you syntax errors. Are you sure you are using MSDos?foxidrive

9 Answers

70
votes

I realize you've found another answer - but the fact is that your original code was nearly correct but for a syntax error.

Your code contained the line

set /A COUNTER=%COUNTER%+1

and the syntax that would work is simply...

set /A COUNTER=COUNTER+1

See http://ss64.com/nt/set.html for all the details on the SET command. I just thought I'd add this clarification for anyone else who doesn't have the option of using FreeDOS.

5
votes

Indeed, set in DOS has no option to allow for arithmetic. You could do a giant lookup table, though:

if %COUNTER%==249 set COUNTER=250
...
if %COUNTER%==3 set COUNTER=4
if %COUNTER%==2 set COUNTER=3
if %COUNTER%==1 set COUNTER=2
if %COUNTER%==0 set COUNTER=1
4
votes

A little bit late for the party, but it's an interessting question.

You can write your own inc.bat for incrementing a number.
It can increment numbers from 0 to 9998.

@echo off
if "%1"==":inc" goto :increment

call %0 :inc %counter0%
set counter0=%_cnt%
if %_overflow%==0 goto :exit 

call %0 :inc %counter1%
set counter1=%_cnt%
if %_overflow%==0 goto :exit 

call %0 :inc %counter2%
set counter2=%_cnt%
if %_overflow%==0 goto :exit 

call %0 :inc %counter3%
set counter3=%_cnt%
goto :exit

:increment
set _overflow=0
set _cnt=%2

if "%_cnt%"=="" set _cnt=0

if %_cnt%==9 goto :overflow
if %_cnt%==8 set _cnt=9
if %_cnt%==7 set _cnt=8
if %_cnt%==6 set _cnt=7
if %_cnt%==5 set _cnt=6
if %_cnt%==4 set _cnt=5
if %_cnt%==3 set _cnt=4
if %_cnt%==2 set _cnt=3
if %_cnt%==1 set _cnt=2
if %_cnt%==0 set _cnt=1
goto :exit

:overflow
set _cnt=0
set _overflow=1
goto :exit

:exit
set count=%counter3%%counter2%%counter1%%counter0%

A sample for using it is here

@echo off
set counter0=0
set counter1=
set counter2=
set counter3=

:loop
call inc.bat
echo %count%
if not %count%==250 goto :loop
2
votes

I've found my own solution.

Download FreeDOS from here: http://chtaube.eu/computers/freedos/bootable-usb/

Then using my Counter.exe file (which basically generates a Counter.txt file and increments the number inside every time it's being called), I can assign the value of the number to a variable using:

Set /P Variable =< Counter.txt

Then, I can check if it has run 250 cycles by doing:

if %variable%==250 echo PASS

BTW, I still can't use Set /A since FreeDOS doesn't support this command, but at least it supports the Set /P command.

1
votes

I built my answer thanks to previous contributors.

Not having time for a custom counter.exe, I downloaded sed for FREEDOS.

And then the batch code could be, emulating "wc -l" with the utility sed, something like this according to your loop (I just use it to increment through executions starting from "1" to n+1):

Just remember to manually create a file "test.txt" with written on the first row

0


sed -n '$=' test.txt > counter.txt
set /P Var=< counter.txt
echo 0 >> test.txt
1
votes

I didn't use DOS for - puh - feels like decades, but based on an old answer and my memories, the following should work (although I got no feedback, the answer was accepted, so it seems to work):

@echo off
  REM init.txt should already exist
  REM to create it:
  REM   COPY CON INIT.TXT
  REM   SET VARIABLE=^Z
  REM ( press Ctrl-Z to generate ^Z )
  REM
  REM also the file "temp.txt" should exist.
REM add another "x" to a file:
echo x>>count.txt
REM count the lines in the file and put it in a tempfile:
type count.txt|find /v /c "" >temp.txt

REM join init.txt and temp.txt to varset.bat:
copy init.txt+temp.txt varset.bat
REM execute it to set %variable%:
call varset.bat

for %%i in (%variable%) do set numb=%%i
echo Count is: %numb%
   REM just because I'm curious, does the following work? :
   set numb2=%variable%
   echo numb2 is now %var2%
if %numb%==250 goto :finished
echo another boot...
warmboot.exe
:finished
echo that was the last one.

In DOS, neither set /a nor set /p exist, so we have to work around that. I think both for %%i in (%variable%) do set numb=%%i and set numb2=%variable% will work, but I can't verify.

WARNING: as there is no ">" or "<" comparison in DOS, you should delete the batchfile at the :finished label (because it continues to increment and 251 is not equal 250 anymore)

(PS: the basic idea is from here. Thanks foxidrive. I knew, I knew it from StackOverflow but had a hard time to find it again)

1
votes

Directly from the command line:

 for /L %n in (1,1,100) do @echo %n

Using a batch file:

 @echo off
 for /L %%n in (1,1,100) do echo %%n

Displays:

 1
 2
 3
 ...
 100
1
votes

Coming to the party very very late, but from my old memory of DOS batch files, you can keep adding a character to the string each loop then look for a string of that many of that character. for 250 iterations, you either have a very long "cycles" string, or you have one loop inside using one set of variables counting to 10, then another loop outside that uses another set of variable counting to 25.

Here is the basic loop to 30:

@echo off
rem put how many dots you want to loop
set cycles=..............................
set cntr=
:LOOP
set cntr=%cntr%.
echo around we go again
if "%cycles%"=="%cntr%" goto done
goto loop
:DONE
echo around we went
-2
votes

None of these seemed to work for me:

@ECHO OFF

REM 1. Initialize our counter
SET /A "c=0"

REM Iterate through a dummy list. 
REM Notice how the counter is used: "CALL ECHO %%c%%" 
FOR /L %%i in (10,1,20) DO (

  REM 2. Increment counter
  SET /A "c+=1"

  REM 3. Print our counter "%c%" and some dummy data "%%i"
  CALL ECHO Line %%c%%: - Data: %%i
)

The answer was extracted from: https://www.tutorialspoint.com/batch_script/batch_script_arrays.htm (Section: Length of an Array)

Result:

Line 1: - Data: 10
Line 2: - Data: 11
Line 3: - Data: 12
Line 4: - Data: 13
Line 5: - Data: 14
Line 6: - Data: 15
Line 7: - Data: 16
Line 8: - Data: 17
Line 9: - Data: 18
Line 10: - Data: 19
Line 11: - Data: 20