5
\$\begingroup\$

Just a fun batch file I have made. I wanted an easy way to loop any arbitrary command several times: loopme.bat

@echo off
SETLOCAL
echo LoopMe v1.0

IF "%~1"=="/?" (GOTO HELP)
IF "%~1"=="" (GOTO HELP)
IF "%2"=="" (SET TIMEOUT=1) ELSE (SET TIMEOUT=%2)
SET COMMAND=%~1
SET COUNTER=0

:RUN
SET /A COUNTER=%COUNTER% + 1
CMD /C "%COMMAND%"
echo.
echo Command  : "%COMMAND%"
echo Times run: %COUNTER%
CHOICE /C QC /N /T %TIMEOUT% /D C /M "Press Q to quit, otherwise wait %TIMEOUT% second(s) to run again."
IF "%ERRORLEVEL%"=="1" (GOTO EOF) ELSE (GOTO RUN)

:HELP
echo Perform the same command in a loop. 
echo Commands containing ^& or ^| must be escaped with ^^
echo Commands containing variables must be escaped with ^^ in the varible name
echo Optionally specify loop time. Default is 1 second.
echo.
echo Usage: loopme dir 2                             
echo               [run dir in current, loop 2 seconds]
echo.
echo        loopme "cls ^& netstat -an ^| find ".109""
echo               [clear screen then run netstat with find filter, loop 1 second]
echo.
echo        loopme "echo %%^time%%" 
echo               [display the time, loop 1 second]
echo
echo.

:EOF

Any improvements or suggestions?

p.s this is my new way to annoy colleagues who leave their workstation unlocked:

loopme "color %^time:~9,2% ^&echo. ^& echo. ^&echo. ^& echo YOU HAVE BEEN HACKED!! ^& echo. ^&echo."
\$\endgroup\$
7
\$\begingroup\$

If you want an easy way to loop an arbitrary command several times...

set /a loop=100
for /L %%P in (1,1,%loop%) do (
    echo Looping for one hundred times
)

The first line is obvious.

The second line is a bit harder - for /L specifies that for every number in a certain set, the batch file will do something. %%P is a parameter that holds what number the for loop is at currently - it can be any letter you like (and some other characters but they are dangerous so stick with letters). in (1,1,%loop%) specifies that this is for every number from 1 to %loop%, increasing by 1 every time. do ( ... ) obviously tells the batch file what it needs to do.

So, in every number from 1 to 100, it will echo Looping for one hundred times. This will obviously scroll down the page seeing as we never clear the screen with cls.

Once a for loop has reached its final number, the batch file continues on executing the commands following the final ) as you would expect.

I can expand this answer if you want to know what you're doing wrong and right in your own code example, but I pretty much just did the same thing in 4 lines which should suffice.


And here comes the expansion. Please note that your code is pretty close to perfect, and these tips only encourage good scripting habits.

To begin with, you spelt variable as varible in line 3 of the :HELP label.

First line of the :RUN label:

set /a counter=%counter% + 1

Instead of this, one can do

set /a counter+=1

This isn't incredibly helpful at the moment, but when you want to add a variable to another variable...

set /a varA+=%varB%

This also works for other operators...

set /a varA*=%varB%

And slightly more complex equations...

set /a varA-=%varB% * %varC%

Which will evaluate %varB% * %varC%, then subtract the result from varA

The command CMD /C "%COMMAND%" is not entirely necessary to my knowledge - simply writing %COMMAND% on a new line will cause the batch parser to expand it, so if %COMMAND% is set as exit, the line will read, at run time, exit. This enables you to use this method rather than the entire CMD /C method.

Another concern that could become more than just a concern is your method for checking the errorlevel - there's a problem. Checking with quotes and == denotes a string comparison - never good when you're dealing with two numbers. So you'll need a fix for this problem, and luckily it's quite simple.

if %errorlevel% EQU 1 ( ... )

This tests for a mathematical equivalence - always good when you're dealing with two numbers. All the operators for mathematical equivalencies are...

EQU - 'equal to'
NEQ - 'not equal to'
GTR - 'greater than'
LSS - 'less than'
GEQ - 'greater than or equal to'
LEQ - 'less than or equal to'

And finally, using if varA==varB (goto label) is not necessary - it works just as well as if varA==varB goto label. The only time you need brackets is when you plan on conditionally executing multiple lines or if you need to use else (just to be safe). When using brackets, always remember to balance them. Indenting isn't required, but it gets really confusing when you start nesting if statements and for loops without it. An example of executing multiple lines...

if %varA% GTR %varB% (
    echo varB is less than varA
    if %varA% GTR %varC% (
        echo varC is less than varA
    ) else (
        echo varC is greater than varA
)

To conclude, your code obviously works fine, but some habits die hard in weird circumstances later on, so it's best to get used to using common conventions (they exist for a reason!). As a side note, remember that batch scripting is not case sensitive. Anything I wrote here, along with anything you wrote, can be written in the opposite case - it has no difference.

\$\endgroup\$
  • 3
    \$\begingroup\$ The best first posts are definitely answers. Exemplified here by you, blaizor. Welcome to CodeReview. \$\endgroup\$ – Legato Apr 19 '15 at 1:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.