logo To Foot
© J R Stockton, ≥ 2012-07-26

MS-DOS Batch Programs.

No-Frame * Framed Index * Frame This
Links within this site :-

Until 2006-10-14, I used Win98 1st Edn.
From 2006-10-19, I used Win XP sp2; from 2008-07-06, XP sp3.

Auxiliary Programs for Batch

The batch capabilities provided by standard MS-DOS are somewhat limited (rival, but non-standard, DOSes offer more), but much can be done with the aid of extra multi-purpose programs and languages.

Batch does not vary much over the range DOS 3.2 to Windows 98, apart from the introduction in Windows 95 of Long File Names and therefore the need to quote them. Batch in Windows NT & XP is considerably different.

Programs in this section are, as far as I know, currently available and free of charge, or standard in some version(s) of MS-DOS/Windows, unless otherwise stated.


For these, see Other Scripting in DOS and Windows. MiniTrue examples are below.

Compiled Languages


My programs and batch files may be freely used, and may be modified. I retain copyright, and therefore they should not be republished.

A Caveat

A PC has two clocks, the DOS (software) one and the RTC (hardware) one; their rate errors will generally differ. MS-DOS, naturally, uses the DOS clock, and so do most programs; some batch programmers access the RTC, favouring BCD. Be careful not to mix similar times from the two sources; the apparent order of events may be wrong, which could lead to logical errors in processing.

See in my Borland Pascal Time and Date.

My Published Programs for DOS Batch Files

These are available from Web directory programs/, as PAS, EXE & ZIP files (and some TXT files), for DOS-16 except as noted. More information is in index. Each program is documented, more or less, by comment in the *.PAS source file, and/or in a *.TXT file. And 32-bit programs are in Index for 32-bit work.

Except where stated, they are 16-bit programs; they should run in MS-DOS and at the MS-DOS prompt in any 16- or 32- bit version of Windows. I think that 32-bit programs may run in 64-bit Windows.

Many of my programs have a 255-character limit on the lengths of input lines and/or of components of output lines.

They require no formal installation or uninstallation; it is merely necessary that the EXE be placed where it can be executed. They use no *.INI files or Registry entries. I suggest using a directory for imports (mine or others'), with a subdirectory for each unit or set of imports. A copy of those to be routinely used can be put in a directory on the Path.

The programs I offer are generally compiled with Borland Pascal 7. Many of my Pascal programs can be compiled by Delphi, and are then only for 32-bit systems. For those who want to use the source files, Pascal compilers are legitimately available on the Net; see my Borland Pascal Procurement and the c.l.p.b mFAQ.

In particular, note :-

HUNT is often adequate on its own - for example

HUNT *.BAK s q b#-7 z+30000 "del" u

will delete all *.BAK files in this directory sub-tree which are both over a week old and at least 30000 bytes long.

Many tasks using these programs only need a single line; see the examples below.

Filter Programs

A Filter uses Standard Input and Output. Some of these currently have little buffering, and could be slow on large files.

Programs For the Environment

Writing to the Environment

These programs use a derived Pascal unit, jrs_envu.pas, for writing to the environment; it is for DOS (not DPMI) mode programs running under DOS to Win98, but not WinNT or WinXP. It is available in the programs/ directory.

LONGCALC, which can write to the Environment, still uses TSUntEnv.pas, obtained from the late Garbo.


These are only usable where jrs_envu.pas works.


To verify that they can access the Environment directly, try STOW, or SET xx=1000000000 after which NOWMINUS f16 Cxx f0 i r ; should show 2001-09-09 01:46:40 and SET xx=1000000000 ; ENVICALC Cxx 1 - Rxx ; should show 1000000000+0999999999 .

In WinNT, use the P or Q options to generate a SET command, redirectable for execution; or see below.

Other Programs

Windows NT/XP

HUNT has been checked, and works, in Windows NT and XP; so the only other thing that should be a problem in these programs for NT/XP is direct writing to the environment (in particular, NOWMINUS, ENVICALC, STOW, NQYR).

I gather that environment storage is different in NT/XP; jrs_envu.pas does not work fully there - to get round this, use the P or Q options, where available, to generate a SET command, redirectable for execution.

NT/XP may run DOS or 16-bit programs in a sub-shell loaded for each.

NT may reduce the console to 80×25 for 16-bit programs.

But Gary Smith reports that

for /f %t in ('nowminus d3 f1 r') do @set THEN=%t

sets THEN correctly in NT.

See also Windows NT +.

Windows Vista & 7

I know nothing of Batch in Vista or Windows 7.

Windows 64-bit

I know nothing of Batch in 64-bit Windows.

Note : by default, 64-bit Windows cannot run 16-bit programs (such as my Pascal ones; my Delphi ones are 32-bit). I have, therefore, written SEAKFYLE.JS, called by SEEK.BAT and run as CScript by Windows Script Host or called by GUI SEEK.HTA, which can be used instead of HUNT.EXE. See in 32-bit index, and first read About SEAKFYLE.JS.

My Published DOS Batch Files

These are in directory programs/, and include :-

(A) : Needs MiniTrue (could use SED?).
(B) : Uses MiniTrue, non-essentially.

Look inside the files for comment. Some need programs from the directory.

Miscellaneous Examples

These may assume UK defaults, for example in date and time representation; changes for others should be easy enough. Names of my programs are in Upper Case.

Examples Using My Programs


Piping through COLS 1- will normalise line-ends, and stop before ^Z; consider also COLS `0 1- . Through SUBS 10=13 | COLS 1- will I think normalise UNIX text files.

To create a file of 40 lines containing "QQ" :-

echo. | COLS !39 | COLS 'QQ > file.ext

To avoid that numerical infelicity :-

echo. | COLS !40 | COLS & : | COLS 'QQ > file.ext
echo. | COLS !40-1 | COLS 'QQ > file.ext

To reverse the line order of a file, in two similar ways :-

type file.ext | COLS ^6,0 1- | sort /r | COLS 7- > file.ext
COLS _5,99999 1- < file.ext | sort | COLS 6- > file.ext

To remove the first 4 lines, pipe through one of

COLS &4 1- :
COLS ]1 [5 1-

COLS can generate simple COM files directly (cf. HALT); using ERRORLEVEL 27 as an example :-

echo.|COLS #184 #27 #76 #205 #33 . > ERRLEV.COM

will generate a file containing

b8 1b 4c  cd 21  0d 0a
  which is
MOV AX, 4C1Bh ; INT 21h ; CrLf.

To convert a long file name to its current short form :-

dir "thp" | find "thp" | COLS `0 1+8 '. 10+3

where "thp" represents the long name; if wild, all are found.

To put the name of the oldest file into Environment variable XX :-

dir *.bak /o:d /b | STOW xx

and for the newest use /o-d.

To list the full names of all subdirectories, omitting the current one :-

dir /s | find "Directory of " | COLS ]1 [2 #34 14- #34

To get an answer line into the Environment :-

COLS < con '@set * 'myvar= 1- .


To rename a file or files to yesterday's date YYYYMMDD :-

NOWMINUS f1 d1 j0 Eeee
ren %1 %eee%.*
set eee=
NOWMINUS f1 d1 j0 r | COLS 'ren * 'xx.* * 1- '.* | MASSEXEC

To put the date in a Pascal Include file, setting a string :-

echo. | date | COLS 'const * 'Today=' 21- & ''; & > today.inc
  giving as : const Today='14/08/2001';
NOWMINUS f1 r | COLS 'const * 'Today=' 1- ''; & > today.inc
  giving as : const Today='2001-08-14';

To determine, by setting or clearing var, whether a file is more than 15 minutes old :-

NOWMINUS F16 ] Ofile.ext Evar [ S#+xx m15 Evar F3 Evar

Save 'now', get fileage, store, restore 'now', subtract fileage, subtract interval; then write to var, which aborts if "new" but otherwise works allowing f3 Evar to wipe var.

See also Stephen Ferg's FDATE.


To read EnvVar DIFSEC, then write EnvVars HH MM SS :-

ENVICALC Cdifsec d 60 %% B10 Ess 60 / d 60 %% Emm 60 / B6 Ehh

To set the month and day of Gregorian Easter 2000 :-



More examples for specific programs are in NOWMINUS.TXT, ENVICALC.TXT, and for others in the *.PAS source files themselves.

To determine differences between two lists, merge, sort, DEDUPE, sort.

Using MiniTrue

16-bit MiniTrue (MT) works in XP; 32-bit MiniTrue 2.0.2 keyboard/screen interaction did not work properly in XP, since fixed. The following was written for MTR in Win98.

Note : I have set in the Environment "MINITRUE= ... -x-".

MiniTrue returns an ERRORLEVEL; use option -n and get 0 for match, 1 for no match, 2 for error - see "Return Values" in the Help.

MiniTrue can indent a (batch) file for printing :-

mtr -x+ -o File.bat - ^(.*)$ = "   \1"  >  prn

It can join two lines in a file (take care with multiple lines) :-

echo.|date|find "Current" >  $888.txt
echo.|time|find "Current" >> $888.txt
mtr -xnb- $888.txt - "(.*)(\r\n)(.*)" = "\1 + \3"
type $888.txt

It can convert multi-line paragraphs into one-long-line ones :-

mtr -x+ -n file.txt - \r\n\r\n = \r\n\r\n \r\n = \x20

It can, in Win98 at least, find the dates of Passover, Kalevala, etc. :-

mtr -ro^ \outlook.txt - passover

MTR can locate, for optional reduction, duplicated words :-

mtr -w -x+ %1 - "(\w+)\s+\1" = "\1"

Here's a demonstration of a generalisable look-up mechanism :-

    set WOT=d
    echo abcdefghijklmnopqrstuvwxyza | mtr -xo .*%WOT%(\w).* = \1
→   e

    set WOT=Mon
    echo Sun Mon Tue Wed Thu Fri Sat Sun | mtr -xo .*%WOT%.(\w+).* = \1
→   Tue

    set WOT=Tue
    echo Mon Montag Tue Dienstag ... | mtr -xo ".*%WOT% (\w+).*" = \1
→   Dienstag

Errorlevel will be set.

Note : A command like mtr -r \outlook.txt - passover can give a brief

mtr: \outlook.txt: No such file or directory (ENOENT)

but succeed.

File Names

MiniTrue has UNIX-like wildcards in filenames; so

mtr -o/ *.[a-z][a-z][02468]

lists all files in the directory with extensions of the form letter letter even-digit. Other options can, of course, be used as well; -r for recurse-directory-tree, for example.


MiniTrue can put environment information into a file :-

mtr -n file.txt - placeholder = %EnvVar%

It can be used to prepare information for loading into the environment :-

 echo.|date|find "Current" > $888.bat
 echo.|time|find "Current" >> $888.bat
 mtr -xnb- $888.bat - "[^\d]*(\d\d)/(\d\d)/(\d\d)(\d\d)(\r\n)[^\d]*(\d\d).*" = "set q=\4\2\1\6"
 call $888
 del $888.bat

Bits of the "mtr" line may be superfluous. UK formats assumed. This will destroy any previous $888.bat, and will set the environment variable Q to date YYMMDDhh, perhaps for later file renaming (and the "set" could be converted to a "ren"). For that job, however, NOWMINUS i0 j0 b3 l8 pq is better.

MiniTrue can be parameter-driven to test an environment variable ST with a RegExp RE, setting ErrorLevel :-

set RE=\d\d:\d\d
set ST=11:15
echo %ST% | mtr -x+ -n - %RE%

Using "UNIX" Utilities

SED, GAWK, and others have been ported from UNIX to MS-DOS. Note that in some cases the port may only be fully satisfactory for North American use, because of simplified handling of date/time localisation.

Long and Short File Names

See also MS-DOS Batch Introduction Page.

In MS-DOS, file names are held in 8+3 format, in 11 bytes. Each of those may be given any value from 0 to 255 by low-level tools, but names created through the OS are more limited.
  (A) There is an explicitly allowed set of characters.
  (B) Upper-half characters can be used; in the first position, sigma is special.
  (C) Lower case letters cannot occur, being made upper case.
  (D) Characters with special meaning cannot occur.
Later Windows-32, however, allows lower case letters.

(A) ! # $ % & ' ( ) - 0-9 @ A-Z ^ ` { } ~ (check those)
(B) £ (GBP) and others
(C) a-z
(D) . : / \ and others including whitespace and newlines

When a given file name does not match 8.3 format, or has characters not allowed in the MS-DOS name field, then a "Long File Name" is generated.

It can be useful to discriminate between files whose names only need the short form and those which need, or may need, the long form. The system needing to do so may or may not itself have LFN capability.

Method 1

For that, one can test the characters of the name as given by dir /b against the set of common MS-DOS characters, here represented by just [A-Z 0-9 dollar minus].

With SED :-

(a)  dir /b | sed -e /^[A-Z0-9$-]\{1,8\}\.[A-Z0-9$-]\{1,3\}/!D
(b)  dir /b | sed -e /^[A-Z0-9$-]\{1,8\}\.[A-Z0-9$-]\{1,3\}/D

In that, (a) will output the names which are certainly short & have extensions, and (b) will output all of the others - I think - but what about RegExp $?.

Better with MiniTrue :-

(c)  dir /b | mtr -o  -x+ -c- ^[A-Z0-9$-]{1,8}(\.[A-Z0-9$-]{1,3})?\r
(d)  dir /b | mtr -o~ -x+ -c- ^[A-Z0-9$-]{1,8}(\.[A-Z0-9$-]{1,3})?\r

Use -o/ -o/~ to test for the presence of one or other type of name.

A filter program written in a HLL could be better.

Consider and test the above even more carefully than usual.

Method 2

Where "DOS" dir /v exists, which it does at least in Win98, I imagine that it always shows first the SFN in traditional style then last after Column 80 (so that it wraps) the LFN.

If so, then comparing the compressed SFN part with the LFN part should do - i.e. start with :-

dir /v | COLS ` 1-8 '. 10-12 #13 #10 `` 81- | DEDUPE . | ...

The idea is that SFN-only files will have one-line entries starting 2 and SFN+LFN files will have two-line entries starting 1.

One could clean up the top and tail of the list with COLS or otherwise, but the distinction has been made (except for extensionless SFN-only files).

However, for those accustomed to writing suited-to-purpose HLL tools, the obvious move (for any system in which dir /v shows SFN & LFN recognisably) is to write a filter program NAMETYPE for use as

dir *.* /v [/a:?] [/o:?] | NAMETYPE <parameter-list>

where the parameters tell whether long names, short names, booleans of existence, counts thereof, or whatever are to be output. I've completed a test version of the program, in directory programs/.

Method 3

A 32-bit non-filter program could be written, using the Win32 API instead of dir /v input.

See also my MS-DOS Batch Files and MS-DOS Batch Introduction.
Home Page
Mail: no HTML
© Dr J R Stockton, near London, UK.
All Rights Reserved.
These pages are tested mainly with Firefox and W3's Tidy.
This site, http://www.merlyn.demon.co.uk/, is maintained by me.