| DosTips.com ... for VISTA,XP,NT,Server 2000,Server 2003,Server 2008 |
|
Last update: Dec 18, 2008 |
DOS - Function
Collection
The functions listed in this
section serve as copy source to enhance your batch program. Simply copy paste the function into your
batch program and start calling them.
The provided test codes serve as examples on how to call the functions.
2 String Trimming Left
and Right - :trim, :trimLeft, :trimRight
4 Time Of Day and runtime
measurements - :getTod, :getHHMMSSDD, :Tod2Str, :TodDiffNow
5 Circulate thru a List -
:getNextInList
6 Choose from List of
last entered Values - :choiceListInput
7 Opening the Registry
Editor at a defined Location - :regedit
8 Float <-> Integer
Conversion - :F2I, :I2F
9 Extracting text blocks
from a File - :extractFromFile
10 Get THIS computers
IP address - :getIP
12 Progress Indicator -
:initProgress, :doProgress
1
Variable Persistency
- :setPersist, :getPersistentVars, :savePersistentVars,
:restorePersistentVars
|
|
|
|
Variable persistency can be
archived by storing the variable of interest into a file when the DOS batch
terminates and read them back in when the DOS batch starts up. The setPersist
function marks a variable to be persistent.
The savePersistentVars
function stores the persistent variables into a file. The restorePersistentVars
function reads the variables back in from a file. |
|
What
it’s good for |
·
Remembering the
state of the batch program for the next run ·
Allow user profiles ·
Store information to
be used in the next run ·
Implement execution
counters |
|
Code |
:setPersist -- to be called to initialize persistent variables :: -- %*: set command arguments set %* GOTO:EOF :getPersistentVars -- returns a comma separated list of persistent
variables :: -- %~1: reference to return
variable SETLOCAL set retlist= set parse=findstr /i
/c:"call:setPersist" "%~f0%"^|find /v
"ButNotThisLine" for /f "tokens=2 delims== "
%%a in ('"%parse%"') do (set retlist=!retlist!%%a,) ( ENDLOCAL & REM RETURN VALUES
IF "%~1" NEQ "" SET %~1=%retlist% ) GOTO:EOF :savePersistentVars -- Save values of persistent variables into a file :: -- %~1: file name SETLOCAL echo.>"%~1" call :getPersistentVars persvars for %%a in (%persvars%) do (echo.SET
%%a=!%%a!>>"%~1") GOTO:EOF :restorePersistentVars –- Restore the values of the persistent variables :: -- %~1: batch file name
to restore from if exist "%FilePersist%"
call "%FilePersist%" GOTO:EOF |
|
|
|
|
Test Code |
rem.--define the filename where
persistent variables get stored rem.
just add a + to the name of THIS file, i.e. "DosTips.bat" -
"DosTips+.bat" set FilePersist=%~dpn0+%~x0 rem.--initialize the persistent
variables call:setPersist var=Hello rem.--read the persistent variables
from the storage call:restorePersistentVars
"%FilePersist%" rem.--modify the persistent variable echo.var = '%var%' echo. echo.Enter new string for var then
run the batch again. set /p var=var = rem.--save the persistent variables
to the storage call:savePersistentVars
"%FilePersist%" |
|
|
|
|
Test Code Output |
var = 'Hello' Enter new string for var then run the
batch again. var = |
2
String Trimming Left
and Right - :trim, :trimLeft, :trimRight
|
|
|
|
Three functions to trim spaces
around a value, i.e. left, right, left and right. |
|
Code |
:trimLeft -- trim leading spaces : -- %~1: variable reference, string
to be trimmed for /f "tokens=* delims= "
%%a in ("!%~1!") do set %~1=%%a GOTO:EOF :trimRight -- trim trailing spaces : -- %~1: variable reference, string
to be trimmed SETLOCAL :trimLeft_LOOP set s=!%~1! if "%s:~-1%"==" "
set s=%s:~0,-1%&goto:trimLeft_LOOP (ENDLOCAL & REM.-- RETURN VALUES
IF "%~1" NEQ "" SET %~1=%s% ) GOTO:EOF :trim -- trim leading and trailing spaces :
-- %~1: variable reference, string to be trimmed call:trimLeft %~1 call:trimRight %~1 GOTO:EOF |
|
|
|
|
Test Code |
set s=left trim nothing& call:trimLeft
s&echo."!s!" set s= left trim one& call:trimLeft
s&echo."!s!" set s= left trim
plenty&call:trimLeft s&echo."!s!" set s=right trim nothing& call:trimRight
s&echo."!s!" set s=right trim one & call:trimRight
s&echo."!s!" set s=right trim plenty &call:trimRight
s&echo."!s!" set s=trim nothing& call:trim
s&echo."!s!" set s= trim one left and one right
& call:trim
s&echo."!s!" set s= trim plenty left and right &call:trim
s&echo."!s!" |
|
|
|
|
Test Code Output |
"left trim nothing" "left trim one" "left trim plenty" "right trim nothing" "right trim one" "right trim plenty" "trim nothing" "trim one left and one
right" "trim plenty left and
right" |
3
String Length -
:strLen
|
|
|
|
The :strLen function uses a
binary search approach to determine the length of a string. |
|
Code |
:strLen -- returns the length of a string via binary search, maximum
length 1023 :: -- %~1: in - varible name of a string
variable :: -- %~2: out- string length SETLOCAL set str=A!%~1!& rem keep the A up front to ensures we get
the length and not the upper bond rem it also avoids trouble in
case of empty string set len=0 set /a n=1024 set /a n^>^>=1, len+=n if !str:~%len%!. == . set /a len-=n set /a n^>^>=1, len+=n if !str:~%len%!. == . set /a len-=n set /a n^>^>=1, len+=n if !str:~%len%!. == . set /a len-=n set /a n^>^>=1, len+=n if !str:~%len%!. == . set /a len-=n set /a n^>^>=1, len+=n if !str:~%len%!. == . set /a len-=n set /a n^>^>=1, len+=n if !str:~%len%!. == . set /a len-=n set /a n^>^>=1, len+=n if !str:~%len%!. == . set /a len-=n set /a n^>^>=1, len+=n if !str:~%len%!. == . set /a len-=n set /a n^>^>=1, len+=n if !str:~%len%!. == . set /a len-=n set /a n^>^>=1, len+=n if !str:~%len%!. == . set /a len-=n ( ENDLOCAL & REM RETURN VALUES
IF "%~2" NEQ "" SET %~2=%len% ) GOTO:EOF |
|
|
|
|
Test Code |
for /l %%a in (0,1,10) do (
set s=
for /l %%b in (0,1,%%a) do if /i %%b NEQ 0 set s=!s!x
call:strLen s len
echo."!s!" - length !len! ) |
|
|
|
|
Test Code Output |
"" - length 0 "x" - length 1 "xx" - length 2 "xxx" - length 3 "xxxx" - length 4 "xxxxx" - length 5 "xxxxxx" - length 6 "xxxxxxx" - length 7 "xxxxxxxx" - length 8 "xxxxxxxxx" - length 9 "xxxxxxxxxx" - length 10 |
4
Time Of Day and
runtime measurements - :getTod, :getHHMMSSDD, :Tod2Str, :TodDiffNow
|
|
|
|
The getTod function returns a Time Of Day (Tod) integer value with a
precision of 1/100th of a second.
Together with the other functions this can be used for time capture
calculations like runtime measurements. The getHHMMSSDD function allows
extracting the hours, minutes, seconds, and 1/100th of seconds
from a Tod integer. The Tod2Str function allows to
freely format a Tod integer into a string, i.e. put the seconds, hours,
minutes where you want them. |
|
What it’s good for |
·
Runtime measurement |
|
Limits |
·
No corrector for
days where daylight saving time is being turned on or off |
|
Code |
:getTod -- get a Time of Day value in 1/100th seconds ::
-- %~1: out - timo of day SETLOCAL set /a t=0 for /f "tokens=1-4
delims=:." %%a in ("%time: =0%") do set /a
t=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100 ( ENDLOCAL & REM RETURN VALUES
IF "%~1" NEQ "" SET %~1=%t% ) GOTO:EOF :getHHMMSSDD -- split a Time Of Day integer into hours, minutes,
seconds, 1/100th :: -- %~1: in - time of day as integer :: -- %~2: out - hours :: -- %~3: out - minutes :: -- %~4: out - seconds :: -- %~5: out - 1/100th SETLOCAL set /a t=%~1 set /a hh=t/360000 set /a t-=hh*360000 set /a mm=t/6000 set /a t-=mm*6000 set /a ss=t/100 set /a t-=ss*100 ( ENDLOCAL & REM RETURN VALUES
IF "%~2" NEQ "" SET %~2=%hh%
IF "%~3" NEQ "" SET %~3=%mm%
IF "%~4" NEQ "" SET %~4=%ss%
IF "%~5" NEQ "" SET %~5=%t% ) GOTO:EOF :Tod2Str -- format a Time Of Day integer into a time string :: -- %~1: out - output string :: -- %~2: in - time of day :: -- %~3: in - formatter string, default is HH:MM:SS.DD SETLOCAL set tod=%~2 set f=%~3 if "%f%"=="" set
f=[TTTT]& rem --if no
format given assume [TTTT] format set
f=%f:[TTTT]=[H]:[MM]:[SS].[DD]%&
rem --replace [TTTT] with the default format call:getHHMMSSDD tod h m s
d& rem --extract the
numbers from the Time Of Day value rem -- ensure two digits, add leading
0 where necessarily set HH=0!h!&set HH=!HH:~-2! set MM=0!m!&set MM=!MM:~-2! set SS=0!s!&set SS=!SS:~-2! set DD=0!d!&set DD=!DD:~-2! rem -- replace the format specifyiers
with real values set f=!f:[HH]=%HH%! set f=!f:[MM]=%MM%! set f=!f:[SS]=%SS%! set f=!f:[DD]=%DD%! set f=!f:[H]=%h%! set f=!f:[M]=%m%! set f=!f:[S]=%s%! set f=!f:[D]=%d%! ( ENDLOCAL & REM RETURN VALUES
IF "%~1" NEQ "" (SET %~1=%f%) ELSE (ECHO.%f%) ) GOTO:EOF :TodDiffNow -- echos the time of day difference of Now-Base :: -- %~1: in - Base time as variable :: -- %~2: in - formatter string,
default is HH:MM:SS.DD :: -- %~3: out- diff time or empty for
screen output SETLOCAL set base=!%~1! call:getTod curr& rem --get the current
Time Of Day set /a diff=curr-base& rem --subtract the base to get the
difference if /i diff LSS 0
diff+=24*60*60*100& rem --when measuring over midnight add a full day call:Tod2Str s %diff%
"%~2"& rem
--format the difference as string ( ENDLOCAL & REM RETURN VALUES
IF "%~3" NEQ "" (SET %~3=%s%) ELSE (ECHO.%s%) ) GOTO:EOF |
|
|
|
|
Test
Code |
set delay=5 call:getTod
t echo.Starting
a %delay%s delay via ping... FOR /l %%a
in (%delay%,-1,1) do ping -n 2 -w 1 127.0.0.1>NUL echo....finished. call:TodDiffNow
t "The %delay%s delay via ping really took [TTTT]" |
|
|
|
|
Test
Code Output |
Starting a 5s delay via ping... ...finished. The 5s delay via ping really took
0:00:06.39 |
|
|
|
5
Circulate thru a
List - :getNextInList
|
|
|
|
The getNextInList function allows a variable to circulate thru a set
of values. Each time calling this
function the next entry in the choice list will be returned. After passing the last entry the function
will start again with the first entry. |
|
What it’s good for |
·
Creating a state automat
in DOS ·
Let the user
circulate through option rather than force typing. |
|
Code |
:getNextInList -- return next value in list :: -- %~1 - in/out ref to current
value, returns new value :: -- %~2 - in choice list, must start with delimiter
which must not be '@' SETLOCAL set lst=%~2& rem.-- get the choice list if "%lst:~0,1%" NEQ
"%lst:~-1%" echo.ERROR Choice list must start and end with the
delimiter&GOTO:EOF set dlm=%lst:~-1%& rem.-- extract the delimiter used set old=!%~1!& rem.-- get the current value set fst=&for /f
"delims=%dlm%" %%a in ("%lst%") do set
fst=%%a&rem.--get the first entry rem.-- replace the
current value with a @, append the first value set lll=!lst:%dlm%%old%%dlm%=%dlm%@%dlm%!%fst%%dlm% rem.-- get the
string after the @ for /f "tokens=2 delims=@"
%%a in ("%lll%") do set lll=%%a rem.-- extract the
next value for /f "delims=%dlm%" %%a
in ("%lll%") do set new=%%a ( ENDLOCAL & REM RETURN VALUES
IF "%~1" NEQ "" (SET %~1=%new%) ELSE (echo.%new%) ) GOTO:EOF |
|
|
|
|
Test Code |
rem.--modify the persistent variable set choiceList=,MO,TU,WE,TH,FR,SA,SU, echo.choice list =
"%choiceList%" set var= echo.var =
'%var%'&call:getNextInList var "%choiceList%" echo.var =
'%var%'&call:getNextInList var "%choiceList%" echo.var =
'%var%'&call:getNextInList var "%choiceList%" echo.var =
'%var%'&call:getNextInList var "%choiceList%" echo.var = '%var%'&call:getNextInList
var "%choiceList%" echo.var =
'%var%'&call:getNextInList var "%choiceList%" echo.var =
'%var%'&call:getNextInList var "%choiceList%" echo.var =
'%var%'&call:getNextInList var "%choiceList%" echo.var =
'%var%'&call:getNextInList var "%choiceList%" echo.var =
'%var%'&call:getNextInList var "%choiceList%" |
|
|
|
|
Test Code Output |
choice list =
",MO,TU,WE,TH,FR,SA,SU," var = '' var = 'MO' var = 'TU' var = 'WE' var = 'TH' var = 'FR' var = 'SA' var = 'SU' var = 'MO' var = 'TU' |
|
Note |
If var starts out empty or with
a bogus value then the getNextInChoiceList function will assign the first
value in the choice list, which is nice default behavior. |
6
Choose from List of last entered Values -
:choiceListInput
|
|
|
|
The choiceListInput function lets the user enter a value. The value entered is returned by the
function and added to the end of a choice list. The choice list is shown next time this
function is being called, and thus allows the user to pick from the list of
last entered value. The last chosen or
newly entered value is added to the end of the choice list and acts as
default input next time this function is being called. The choice list is being stored
into a variable. The name of this
variable is to be passed into the function, which allows this function to be
called using different choice lists. |
|
What it’s good for |
·
Increases user
efficiency ·
Allows picking
number from list instead of having to enter a long strings ·
Only need to pick a
value when different from last run, otherwise just hit enter |
|
Tip |
Make the choice list variable
persistent in order to have it available over multiple batch file executions. |
|
Code |
:choiceListInput – lets the user choose from list of last entered values : -- %~1 - out, returns input
value : -- %~2 - in/out, ref to
choice list, returns trimmed reordered choice list : -- %~3 - in, list title : -- %~4 - in, list entry count
limit SETLOCAL ENABLEDELAYEDEXPANSION set l=,!%~2!,& rem.-- get the choice list set t=%~3& rem.-- get the list title set c=%~4& rem.-- get the list entry count
limit set m=& rem.-- a message set l2=, set v= :choiceListInput_LOOP1 echo.%t% set i=0&for %%a in (%l%) do ( set
/a i+=1
set l2=!l2!!i!;%%~a,
set v=%%~a
echo. !i! - %%~a ) if "%m%" NEQ ""
echo. ^>^> %m% echo.
Make a choice or enter a new value [%v%] set v1=%v% set /p v1= : echo. set v2=!v1!&set
v2=!v2:,=!&set v2=!v2:@=!&set v2=!v2:;=!&set v2=!v2:"=! rem.--reject entry with illegal
character if "!v1!" NEQ
"!v2!" (
set m=Note: ,;@" and empty string not allowed. Try again.
goto:choiceListInput_LOOP1 ) rem.--if first character is minus
then remove the entry set remove=&if "%v1:~0,1%"=="-"
set remove=y&set v1=%v1:~1% set v=%v1% rem.--if number chosen then find
corresponding value set l3=!l2:,%v%;=,@! if "%l3%" NEQ
"%l2%" (
for /f "delims=@ tokens=2" %%a in ("!l3!") do set
l3=%%a
for /f "delims=,"
%%a in ("!l3!") do set v=%%a ) rem.--remove value from list if exist set l3=%l% set l=!l:,%v%,=,! if
"%remove%"=="y" (
if "%l%"=="%l3%" (set m='%v%' cannot be removed
from list
) ELSE (set m='%v%' has been removed from list)
goto:choiceListInput_LOOP1 ) if "%l%"=="%l3%"
echo. ^>^>'%v%' has been added
to the list rem.--add to the value to the end set l=!l:~1!%v% rem.--enforce the list entry count
limit if requested if "%c%" NEQ "" (
set i=0&for %%a in (%l%) do set /a i+=1
if /i !i! GTR !c! ( for /f "delims=,
tokens=1,*" %%a in ("!l!") do ( set l=%%b echo. ^>^>'%%a' dropped out of the list )
) ) ( ENDLOCAL & REM RETURN VALUES
IF "%~1" NEQ "" (SET %~1=%v%) ELSE (echo.%v%)
IF "%~2" NEQ "" (SET %~2=%l%) ELSE (echo.%l%) ) goto :eof |
|
|
|
|
Test Code |
if "%~1"=="" (
set z=%~dpn0.tmp
if exist "!z!"
echo.a>>"!z!"
echo.b>>"!z!"
echo.c>>"!z!"
echo.d>>"!z!"
echo.>>"!z!"
echo.2>>"!z!"
echo.-d>>"!z!"
echo.-1>>"!z!"
echo.-1>>"!z!"
echo.z>>"!z!"
"%~f0" auto<"!z!" ) rem.--modify the persistent variable set choiceList= set var= call:choiceListInput var choiceList
"Selection List:" 3&echo.
--'!var!' has been selected call:choiceListInput var choiceList
"Selection List:" 3&echo.
--'!var!' has been selected call:choiceListInput var choiceList
"Selection List:" 3&echo.
--'!var!' has been selected call:choiceListInput var choiceList
"Selection List:" 3&echo.
--'!var!' has been selected call:choiceListInput var choiceList
"Selection List:" 3&echo.
--'!var!' has been selected call:choiceListInput var choiceList
"Selection List:" 3&echo.
--'!var!' has been selected call:choiceListInput var choiceList
"Selection List:" 3&echo.
--'!var!' has been selected |
|
Test Code Output |
Selection List:
Make a choice or enter a new value []
:
>>'a' has been added to the list
--'a' has been selected Selection List:
1 - a
Make a choice or enter a new value [a]
:
>>'b' has been added to the list
--'b' has been selected Selection List:
1 - a
2 - b
Make a choice or enter a new value [b]
:
>>'c' has been added to the list
--'c' has been selected Selection List:
1 - a
2 - b
3 - c
Make a choice or enter a new value [c]
:
>>'d' has been added to the list
>>'a' dropped out of the list
--'d' has been selected Selection List:
1 - b
2 - c
3 - d
Make a choice or enter a new value [d]
:
--'d' has been selected Selection List:
1 - b
2 - c
3 - d
Make a choice or enter a new value [d]
:
--'c' has been selected Selection List:
1 - b
2 - d
3 - c
Make a choice or enter a new value [c]
: Selection List:
1 - b
2 - c
>> 'd' has been removed from list
Make a choice or enter a new value [c]
: Selection List:
1 - c
>> 'b' has been removed from list
Make a choice or enter a new value [c]
: Selection List:
1 - c
>> 'b' cannot be removed from list
Make a choice or enter a new value [c]
:
>>'z' has been added to the list
--'z' has been selected |
|
|
|
|
| |