Timo Salmi's Assorted Batch Tricks
Timo Salmi's Assorted Batch TricksProfessor Timo SalmiDepartment of
Accounting and Business FinanceUniversity of Vaasa,
FinlandCo-moderator of news:comp.archives.msdos.announcehttp://garbo.uwasa.fi/ftp://garbo.uwasa.fi/All
rights reservedCopyright (c) 1993-1999 by Timo Salmi ....................................................................
Prof. Timo Salmi Co-moderator of news:comp.archives.msdos.announce
Moderating at ftp:// & http://garbo.uwasa.fi/ archives 193.166.120.5
Department of Accounting and Business Finance ; University of Vaasa
mailto:ts@uwasa.fi ; FIN-65101, Finland
Spam foiling in effect. My email filter autoresponder will return a
required email password to users not yet in the privileges database.
....................................................................
___________________________________________________________
This file belongs with TSBAT*.ZIP. Please do not distribute
this 1BATFAQ file separately! If you see this file
distributed alone, please alert the SysAdmin immediately.
___________________________________________________________
Introduction
Index
Articles
Download the text file version
with samples and utilities
IndexNOTE: To search this
document for a specific keyword, press CTRL+F on your keyboard to use your
browser's text search capability. 1)
How can I make "@echo off" MS-DOS version independent?2)
Deleting all files without being prompted "Are you sure (Y/N)?"3)
Is it possible to nest for loops in batch files?4)
How can I check in a batch whether a directory exists?5)
Checking that a program is available at the current directory or at
path6)
Is it possible to use subroutines and recursion in batches?7)
How can I convert a lowercase parameter to uppercase?8)
Is there an easy way to append a new directory to the path?9)
How can I compare if two files two files are identical?10)
Writing an empty line to the screen. How is that done?11)
A tip: Customizing the pause message12)
A tip: Complicated renaming of files with for13)
How can I check if the file name given included wildcards?14)
Is it possible to prevent the user from breaking the batch?15)
Can I prevent a break from bypassing the autoexec.bat?16)
How can I extract the extension of a file name?17)
Information on the quote character %18)
Eliminating auxiliary batches (making do with the main batch)19)
Utilizing the subst command in paths20)
How can I run a batch once a week (testing for the weekday)21)
How can I test if a given file name includes the path?22)
How can I display the time without having to press enter?23)
Alternatives for testing for the errorlevel value24)
About redirecting a batch file's output25)
How can I test if my batch has sufficient environment space?26)
Is there a simple trick to "disable" or hide a drive?27)
How can I send an escape sequence to the printer?28)
Is it possible to create a random string in a batch?29)
Is it possible in a batch to find out the length of a string?30)
How to obtain the MS-DOS version into an environment variable?31)
How can I find out the number of regular files on a drive?32)
How can I use a batch to augment line numbers to my text file?33)
Storing and returning to the original directory (push and pop)34)
Enticing the current date into an environment variable35)
A tip for power users. Identifying the individual PC.36)
For loop and redirection quirks37)
Is it possible to traverse a directory tree with a batch?38)
It it possible to echo the redirection symbol in a batch?39)
How can I extract the file basename?40)
A batch to put user input into an environment variable41)
How can I get the last replaceable parameter given to a batch?42)
Creating an empty file if the file does not already exist43)
How can I change or remove the disk volume serial number?44)
How to pause in a batch for a preset number of seconds?45)
Where can I find a program to compile batches into COMs or EXEs?46)
How can I test whether a disk is empty or not?47)
How can I run a different batch depending on the weekday?48)
Can one put line numbers into a file with just batch commands?49)
How can I backup from the current directory files made today?50)
How can I traverse all files of a directory in a batch?51)
How can I step through a batch a command at a time to debug it?52)
How to display all files made or updated on a day or today?53)
How can I make a list of all my files and locate a certain file?54)
How can I tell if a batch is running in a Windows dosbox?55)
How can a test that there is a disk in a floppy disk drive?56)
Could you please solve this problem for me with a batch?57)
How can I make a loop that is repeated a preset number of times?58)
How can I display the contents of the memory?59)
How get today's date into a six-character environment variable?60)
How can I find and copy the files updated today in a directory?61)
How can I test in a batch whether a TSR program has been loaded?62)
Putting the current drive letter into an environment variable.63)
How can I extract the drive letter from a full file path?64)
How can I write a "SLEEP" command to pause for a certain time?65)
How can put comments into a batch file?66)
How can I echo just the word "off" in a batch file?67)
How can I extract the first two characters of a file name?68)
How can I compare two numbers with batch commands?69)
All these solutions are for wimps. Why not rather use 4DOS?70)
How can I give more than the nine parameters to a batch?71)
How can I update copy files from one directory to another?72)
How can I best clear all the files from my TEMP directory?73)
How can I check the number of parameters given to a batch?74)
How can I locate and e.g. delete all *.TMP files on a drive?75)
How can I rename all files sequentially in a directory?76)
How to search all the *.txt files on a drive for a word?77)
How can I give multiple commands on one line?78)
Is there a batch to individually zip each file in a directory?79)
A batch to substitute a string through a set of text files?80)
Where do I find a good book or WWW page on batch programming?81)
How to read a file's date and time into environment variables?Introduction
Index
Articles
Download the text file version
with samples and utilities
Articles1. How can I make "@echo off" MS-DOS version independent?
=========================================================
If you want to turn the echo off, and do not wish to show that line
on the screen, you can easily do this by applying
@echo off
There is a catch, however, because this only works since MS-DOS
version 3.30. So if you want to make it general, put the following
line in your autoexec.bat file if you are using MS-DOS 3.30 or
higher
set _echo=@
Then use the following format in your batches, which will then work
for any MS-DOS version
%_echo%echo off
Of course, many if not most users will have a much more recent
MS-DOS version. As we know, the last released independent MS-DOS is
6.22. After that Microsoft has been pushing Windows and trying to
kill its MS-DOS despite the huge use base still left in the world.
How does one find out which MS-DOS version one has? The version
is, of course, given by the VER command. For using this in testing
in a batch see the later item #30 "How to obtain the MS-DOS version
into an environment variable?"
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 2. Deleting all files without being prompted
============================================
One of the most Frequently Asked Questions (FAQs) about batches is
how to suppress the "Are you sure (Y/N)?" confirmation requirement
for del *.*. Use the following:
echo y| del *.*
If you wish to suppress the message too, use
echo y| del *.* > nul
There is also another alternative for doing this:
for %%f in (*.*) do del %%f
If the directory is empty you can avoid the "File not found" message
by applying
if exist *.* echo y| del *.* > nul
Whether or not it is sensible to suppress the confirmation can be
debated, but these are the tricks anyway. Even more dangerous is
using such a trick on DELTREE or FORMAT. Do do not recommend it. In
fact it is better to disable these two commands (so that they will
require a full path, as given in 1DOSTRIK.TXT item "7. Selected
Doskey macro examples".
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 3. Is it possible to nest for loops in batch files?
===================================================
Yes, it is possible to have nested loops of a kind in batch
programming, but not directly. You have to call a second batch file.
Consider the following two batches, and try it out by calling
test.bat.
@echo off
rem TEST.BAT
for %%f in (a b c d e f) do %comspec% /c test2 %%f
@echo off
rem TEST2.BAT
echo.
for %%g in (1 2 3) do echo %1%%g
In the above "%comspec%" has been used for greater generality
across MS-DOS versions. Alternatively you could have
@echo off
rem TEST.BAT
for %%f in (a b c d e f) do call test2 %%f
In TEST2.BAT the line "echo." is only for better readability of the
output.
It is also possible to use only one batch file by letting the
first batch create the second
@echo off
rem TEST.BAT
::
echo @echo off > test$$$2.bat
echo echo. >> test$$$2.bat
echo for %%%%g in (1 2 3) do echo %%1%%%%g >> test$$$2.bat
::
for %%f in (a b c d e f) do call test$$$2 %%f
if exist test$$$2.bat del test$$$2.bat
Note the need of the extra "%":s in echoing from a batch file to
another.
Another alternative is to write everything as below on a *SINGLE*
line:
for %%f in (a b c d e f) do %comspec% /c
for %%g in (1 2 3) do echo %%f%%g
(The wrap has been used in the text is because of the right margin.
Don't wrap your batch.). The disadvantage of this alternative is
that the echo will be on.
In the above you may wonder about the "%COMSPEC% /C" alternative to
"CALL". The comspec is and environment variable that points to the
location of the COMMAND.COM command interpreter. The /C switch tells
that the command interpreter is to exit after performing the
specified line. The /C switch must be the last switch on the command
line. The "%COMSPEC% /C" alternative is available in earlier
versions of MS-DOS than the CALL command.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 4. How can I check in a batch whether a directory exists?
=========================================================
It is sometimes useful to be able to test whether a particular
directory exists. The following test is true if the %1 directory
does not exist.
if not exist %1\nul if not exist %1nul echo Directory %1 does not exist
However, this does not seem to work for a CD-ROM. Probably because
of the CD-ROM drivers use a slightly different directory system with
no . (dot) and .. (dot-dot). My thanks to Bjorn Svensson for
bringing this to my attention.
Further problems are caused by the Windows dosbox / MS-DOS versions
for Windows. Although this FAQ-type file has been written for
vanilla MS-DOS let's consider the alternatives that do not rely on
the \nul trick. One way of testing the existence of a directory is
trying to write a file to it, and testing if the file then exists.
Obviously this trick can't be used for read-only devices like
CD-ROMs and write protected diskettes.
@echo off
if "%1"=="" goto _help
ctty nul
echo.>%1\tmp#$#$#
ctty con
if exist %1\tmp#$#$# echo Directory %1\ exists
if not exist %1\tmp#$#$# echo Directory %1\ does not exist
if exist %1\tmp#$#$# del %1\tmp#$#$#
goto _end
:_help
echo Usage %0 [DirectoryName]
echo No backslash. Root e.g. as C:
echo A subdirectory e.g. as C:\TMP
:_end
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 5. Checking that a program is available at the current directory or at path
===========================================================================
When you call a program from a batch, and do not give the explicit
path to it, it is advisable to test that the program is available
either at the current directory or the default path.
set _found=
if exist %1 set _found=yes
for %%d in (%path%) do if exist %%d\%1 set _found=yes
for %%d in (%path%) do if exist %%d%1 set _found=yes
if "%_found%"=="yes" goto _continue
echo %1 is not at path or the current directory
goto _out
:_continue
echo %1 found at path or in the current directory
:_out
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 6. Is it possible to use subroutines and recursion in batches?
==============================================================
Yes, it is possible to use subroutines within batches. The crucial
trick is setting an environment variable (e.g. _return) to point to
a label where to return after the subroutine has been performed. For
an example see UNPACK.BAT, and BOOT.BAT, the sections :_common and
:_subru.
Likewise it is possible to use recursion to emulate subroutines in
batches. (Recursion means that a batch calls itself).
As an example see SAFEDEL.BAT and trace the effects of the line
for %%f in (%1) do call safedel %%f recurse
Note that safedel could be replaced by %0 because the zeroth
parameter of a batch file points to itself.
Besides the material referred to in the above, below is very simple,
artificial demonstration example of using a subroutine within a
batch file.
@echo off
set name_=FirstName
set return_=_label1
goto _subru
:_label1
::
set name_=SecondName
set return_=_label2
goto _subru
:_label2
echo Done!
goto _end
::
:_subru
echo %name_%
goto %return_%
::
:_end
set name_=
set return_=
Below is the same demonstration using one-level recursion. As you
see, this option is more brief, since no accounting is needed to
keep track of the return points.
@echo off
if "%1"=="recurse" goto _recurse
::
set name_=FirstName
call %0 recurse
::
set name_=SecondName
call %0 recurse
::
echo Done!
goto _end
::
:_recurse
echo %name_%
::
:_end
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 7. How can I convert a lowercase parameter to uppercase?
========================================================
This example shows how to ensure that the parameter %1 given to the
batch is in uppercase. This utilizes the fact that MS-DOS converts
the path to uppercase. The result is stored in upcase_ and then the
original path is restored.
set tmp_=%path%
path=%1
set upcase_=%path%
path=%tmp_%
set tmp_=
The also is another method for getting case-independent results.
This is adapted from Jeff Prosise's column in PC Computing, March
1993, pp. 216-217. If the batch below is called TEST.BAT, it makes
no difference whether you enter "TEST yes" or "TEST YES" or "TEST
yEs".
@echo off
if not "%1"=="" set %1=*****
set status_=
if "%yes%"=="*****" set status_=yes
if "%no%"=="*****" set status_=no
if not "%status_%"=="" echo The parameter %%1 was a %status_%
if "%status_%"=="" echo The parameter %%1 was neither a yes nor a no
if not "%1"=="" set %1=
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 8. Is there an easy way to append a new directory to the path?
==============================================================
This often needed trick is basically very simple. For example
to add directory %1 to path use
path=%path%;%1
Note that you can only use this trick in a batch. It will not work
at the MS-DOS prompt because the environment variables are expanded
(%path%) only within batches.
For a full treatment with safeguards against appending non-existing
directories, or appending twice, see ADDPATH.BAT in the collection.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 9. How can I compare if two files two files are identical?
===========================================================
It is possible in batch programming to test whether or not two files
have identical contents. This trick utilizes the external MS-DOS
programs fc.exe and find.exe. (An external MS-DOS program means, of
course, a program that comes with the standard MS-DOS releases. Most
often the MS-DOS external support files are located in a c:\dos
directory.)
@echo off
fc %1 %2 > tmp$$$
type tmp$$$ | find /i "fc: no differences encountered" > diffe$$$
if exist notsame$ del notsame$
copy diffe$$$ notsame$ > nul
if not exist notsame$ echo Files %1 and %2 are different
if exist notsame$ echo Files %1 and %2 are identical
if exist tmp$$$ del tmp$$$
if exist notsame$ del notsame$
if exist diffe$$$ del diffe$$$
If you think about, this idea can be used for other useful purposes,
too, because it establishes whether a given string is found in a
text file.
The batch in the above is generic across various MS-DOS versions.
For later MS-DOS versions the batch can be simplified since FIND
returns the success of the search as an errorlevel. For more on that
aspect, type "HELP FIND".
@echo off
fc %1 %2 | find /i "FC: no differences encountered" > nul
if errorlevel==2 goto _2
if errorlevel==1 goto _1
echo Files %1 and %2 are identical
goto _continue
:_1
echo Files %1 and %2 are different
goto _continue
:_2
echo Error in the FIND search
:_continue
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 10. Writing an empty line to the screen. How is that done?
==========================================================
This is a simple, but an often needed, useful trick. Just use echo
with (for example) a point (.) right after it. No space. As you can
see, I have utilized this batch feature extensively in my batch
collection.
@echo off
echo Hello world
echo.
echo Batches are fun
Q: A further question. I wanted to create an empty file but after
echo.> tmp
the size of the tmp file is two bytes.
A: Of course it is. The "echo." displays one empty line on the
screen, i.e. inserts an end of line. Thus the contents of the tmp
file will be Hex 0D 0A (ASCII 13, 10 in decimal), just as it should
in MS-DOS. For creating an empty file, please see the relevant,
separate item in this FAQ.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 11. A tip: Customizing the pause message
========================================
You can easily customize the message given by pause by giving your
own with echo and directing the pause message to nul.
to nul.
echo Break to quit, any other key to remove the tmp directory
pause > nul
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 12. A tip: Complicated renaming of files with for
=================================================
A considerable number of batch related questions on Usenet news seem
to relate to different kinds of file name handling. One set of these
questions relate to renaming files. Everyone knows the rudiments
like "REN OLDNAME.* NEWNAME.*" but one can conveniently utilize the
FOR statement for more complicated renaming tasks. Although this is
basically trivial, one does not necessarily come to think of it. The
FOR statement is quite useful for involved renaming of files. An
example delineates. For example I have the following files (Turbo
Pascal units for TP 4.0, 5.0, 5.5, 6.0 and 7.0). Say that I wish to
rename them to be version 35 instead of 34.
tspa3540.zip
tspa3550.zip
tspa3555.zip
tspa3560.zip
tspa3570.zip
The following for-statement does that conveniently.
for %f in (40 50 55 60 70) do ren tspa34%f.zip tspa35%f.zip
Naturally, renaming is not the only task that can utilize this
trick. I am sure you can readily think of others, like
for %d in (a b) do format %d:
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 13. How can I check if the file name given included wildcards?
==============================================================
This example shows how you can easily test whether a parameter (%1)
of a batch contains wildcards.
@echo off
for %%f in (%1) do if "%%f"=="%1" goto _nowilds
echo Parameter %1 contains wildcards (or is missing)
:_nowilds
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 14. Is it possible to prevent the user from breaking the batch?
===============================================================
Yes, it is possible to prevent the user from interrupting a batch by
using the ctty command to reassign the input (and the output)
device. Here is an example (an elementary password batch requiring
inputting an e). Note the < and > redirections which are needed
while the ctty has been assigned to nul. The ASK batch enhancer is
included in the TSBAT collection. (In the later MS-DOS versions you
could as well use the CHOICE command).
@echo off
ctty nul
echo Now you cannot break the batch with ^C or ^Break > con
:_ask
echo Use e to break > con
ask /b /d < con
if errorlevel==101 if not errorlevel==102 goto _out
goto _ask
:_out
ctty con
echo Back to normal. Now you can break the batch with ^C or ^Break.
Note that this trick does not prevent you from rebooting with
alt-crtl-del while the batch is running. For that you need an
external program like noboot.exe from
103201 Mar 28 1998 ftp://garbo.uwasa.fi/pc/ts/tstsr22.zip
TSR programs (noboot,reslock,sordino,timedown,timeup ...)
(or whichever version number is current).
The ASK.EXE usage is
ASK [Prompt] [/b] [/d] [/l] [/t##] [/u]
: : : : +- convert to Upper case
: : : +- Time-out parameter (0 = forever)
: : +- convert to Lower case
: +- Direct read (no <-+ needed)
+- Batch mode (needed only if no prompt)
This question elicits one of the most frequent false answers, i.e.
that the problem is solved by including "BREAK=OFF" in your
CONFIG.SYS file. The BREAK ON/OFF (only) toggles the extended CTRL+C
checking. For more on this see "HELP BREAK".
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 15. Can I prevent a break from bypassing the autoexec.bat?
==========================================================
You can actually prevent a quick tapping of the break from bypassing
your autoexec.bat by a variation of the trick in the item above. Put
for example
shell=c:\command.com /p nul
in your config.sys. Before you do, make sure to have a floppy to
boot from in case something goes wrong. I first saw trick when it
was posted in the Usenet news:comp.os.msdos.programmer newsgroup by
Joseph Gil.
This is not, however, quite all there is to it. You should put
ctty con
as the last line to your autoexec.bat. If you don't, the keyboard
will not be responding, and you must boot from the floppy you so
sensibly had prepared :-).
The /P switch makes a new permanent copy of the command interpreter.
For the details meaning of the /P switch with C:\COMMAND.COM use
"HELP COMMAND".
As you know pressing F5 before CONFIG.SYS in executed skips
CONFIG.SYS and AUTOEXEC.BAT altogether. On the other hand, it is
possible to disable the bypassing. Set in your GONFIG.SYS "SWITCHES
/K". For more see "HELP SWITCHES".
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 16) How can I extract the extension of a file name?
===================================================
It would be quite useful to be able to extract the extension of a
given file name into an environment variable. Or to be able just to
test whether there is an extension. Here is how to do that. The
batch is based on the information in PC-Magazine July 1992, Vol. 11,
No. 13, page 528. It gives the crucial information that if one
precedes the argument of a for loop with a slash (/), then the
argument is interpreted in two parts. The first part is the first
character of the argument, the second part all the rest. Neat,
indeed.
The problem with my solution below is that it will not recognize
.* or .??? as extensions. But, of course, one can first test for
wildcards as shown in a previous item "Checking for wildcards". See
e.g. UNPACK.BAT for the utilization of this method.
@echo off
set exten_=%1
:_next
set prev_=%exten_%
for %%f in (/%exten_%) do set exten_=%%f
if ".%exten_%"=="%prev_%" goto _extfound
if not "%exten_%"=="%prev_%" goto _next
goto _noext
:_extfound
echo The filename %1 has an extension %exten_%
goto _out
:_noext
echo The filename %1 has no extension
:_out
set exten_=
set prev_=
This solution will not work after MS-DOS version 6.22, i.e. it will
not work under Windows95.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 17) Information on the quote character %
========================================
As we know %1 indicates the first parameter given to a batch. Thus
for example echo %1 echoes that parameter. But what if you want to
echo the actual string %1 instead. The % character acts as a quote
character. Thus echo %%1 will indeed be a "%1" instead of its usual
interpretation. Try the following simple test
@echo off
if "%1"=="" goto _out
echo %1
echo %%1
:_out
See the item on "Eliminating auxiliary batches" for utilizing this
feature. A good example of utilizing this feature is given by
DELPATH.BAT. If you prepare a new batch file using a batch file
you'll need to use the % character double. A demonstration:
@echo off
echo> test$$$.bat @echo off
echo>> test$$$.bat if not "%%1"=="" echo %%1
call test$$$ Success
if exist test$$$.bat del test$$$.bat
Had you used only "%1", no "Success".
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 18. Eliminating auxiliary batches (making do with the main batch)
=================================================================
Quite a number of batch programming tasks require an auxiliary batch
which the primary batch has to call. Many of these cases can be
eliminated by making the batch call itself (a kind of recursion).
The auxiliary code is put in the batch itself. The trick is best
illustrated by looking at the SHOW.BAT, which provides a wild-carded
TYPE command, and would normally need an auxiliary file to type each
of the individual files. Another example is given by the SAFEDEL.BAT
batch.
There is also an another trick for a similar purpose. The primary
batch creates and auxiliary batch or batches, which it then calls.
See DELPATH.BAT for an example of this method. Here is also a simple
demonstration listing the drives on your system. (Only from c to t,
actually because of the wrap I use here).
@echo off
echo @echo off> tmp$$$.bat
echo if exist %%1:\nul echo Drive %%1: is present>> tmp$$$.bat
for %%d in (c d e f g h i j k l m n o p q r s t) do call tmp$$$ %%d
del tmp$$$.bat
There was an inventive twist of this method in PC-Magazine August
1992, Vol. 11, No. 14, p. 527 for getting the volume label of a
disk. Here is my own example using the same techniques. It sets the
current directory in an environment variable getdir_. I have
utilized this technique in PUSHDIRE.BAT.
@echo off
echo @echo off> director.bat
echo set getdir_=%%2>> director.bat
echo echo %%getdir_%%>> director.bat
dir | find "Directory"> go.bat
call go
if exist director.bat del director.bat
if exist go.bat del go.bat
Incidentally, this is one example of a batch that will not work in
the Windows 95 DOS box. Since the long file names are supported you
have to use "directory.bat" instead of "director.bat" in the above!
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 19. Utilizing the subst command in paths
========================================
I use the following kind of a simple batch to make some of my
directories easy to reach. The way this simple batch is written it
avoids unnecessary errors if the substitution already has been made.
As a last measure it shows the current substitution status.
@echo off
if exist m:\nul echo The substitution has already been made
if not exist m:\nul subst m: c:\math
if not exist s:\nul subst s: c:\support
subst
A warning. This advice is for vanilla MS-DOS only. If you have
Windows, it is highly inadvisable to use the SUBST command.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 20. How can I run a batch once a week (testing for the weekday)
===============================================================
The crucial trick is to be able to put the weekday into an
environment variable. For the full treatment see WEEKLY.BAT. The
essential trick needed is below, that is capturing the weekday into
a weekday_ environment variable. No auxiliary programs outside the
normal MS-DOS commands are needed.
@echo off
echo.| date | find "Current" > tmp$$$.bat
echo set weekday_=%%3> current.bat
call tmp$$$
echo %weekday_%
if "%weekday_%"=="Fri" echo Thank God it's Friday
if exist tmp$$$.bat del tmp$$$.bat
if exist current.bat del current.bat
set weekday_=
In fact, if you substitute %%4 for the %%3 in the above, you'll
capture today's date. Neat, eh?
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 21. How can I test if a given file name includes the path?
==========================================================
First of all please see the earlier item "How can I extract the
extension of a file name?" because the same ideas are drawn upon.
Testing whether the file name is a bare file name like go.exe or
includes a path like r:\progs\go.exe is quite a complicated task if
one wants to allow wildcarded names like r:\progs\*.exe. This can be
done, and here is how. If one can figure this one out, one can
safely say that one has begun to understand batch files.
@echo off
echo @echo off> tmp$$$.bat
echo set rest_=%%1>> tmp$$$.bat
echo :_next>> tmp$$$.bat
echo set prev_=%%rest_%%>> tmp$$$.bat
echo for %%%%g in (/%%rest_%%) do set rest_=%%%%g>> tmp$$$.bat
echo if ":%%rest_%%"=="%%prev_%%" goto _found>> tmp$$$.bat
echo if "\%%rest_%%"=="%%prev_%%" goto _found>> tmp$$$.bat
echo if not "%%rest_%%"=="%%prev_%%" goto _next>> tmp$$$.bat
echo goto _nopath>> tmp$$$.bat
echo :_found>> tmp$$$.bat
echo set haspath_=yes>> tmp$$$.bat
echo goto _out>> tmp$$$.bat
echo :_nopath>> tmp$$$.bat
echo set haspath_=no>> tmp$$$.bat
echo :_out>> tmp$$$.bat
echo set rest_=>> tmp$$$.bat
echo set prev_=>> tmp$$$.bat
for %%f in (%1) do call tmp$$$ %%f
if "%haspath_%"=="yes" echo Filename %1 includes a path
if "%haspath_%"=="no" echo Filename %1 does not include a path
rem if exist tmp$$$.bat del tmp$$$.bat
set haspath_=
Note: This will not work for MS-DOS 7 (i.e. the Windows95 version).
The above batch is based on an pre-7 MS-DOS quirk that a line like
for %%f in (/name) do echo %%f
will return
n
ame
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 22. How can I display the time without having to press enter?
=============================================================
A simple trick to show the current time:
echo.| time | find /v "new"
For capturing the time into an environment variable see
LASTBOOT.BAT and item #34.
The /V switch means displaying all lines not containing the
specified string. This gets rid of the "Enter new time:" line.
A more complicate way is first getting the time into an
environment variable. A trick utilized also elsewhere in this batcg
FAQ.
@echo off
echo @prompt set time_=$t> tmp$$$.bat
%comspec% /c tmp$$$> tmp2$$$.bat
call tmp2$$$
echo %time_%
del tmp$$$.bat
del tmp2$$$.bat
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 23. Alternatives for testing for the errorlevel value
=====================================================
Many programs and some MS-DOS commands (like diskcomp, format and
xcopy) return an errorlevel exit code on termination. Testing for
the errorlevel is complicated by the cumulative nature of
errorlevels. Thus if you wish to test if the errorlevel was
(exactly) 2, you must use
if errorlevel==2 if not errorlevel==3 echo Errorlevel 2
Another alternative is utilizing the for command:
for %%e in (0 1 2 3 4 5 6 7) do if errorlevel==%%e set _errlev=%%e
if "%_errlev%"=="2" echo Errorlevel 2
Alternatively, and more generally
for %%e in (0 1 2 3 4 5 6 7) do if errorlevel==%%e set _errlev=%%e
if "%_errlev%"=="2" echo Errorlevel %_errlev%
A convenient trick in more complicated batches is using the goto
command:
for %%e in (0 1 2) do if errorlevel==%%e goto _label%%e
goto _out
:_label0
echo Errorlevel 0
:_label1
echo Errorlevel 1
:_label2
echo Errorlevel 2
:_out
See BOOT.BAT for actual usage of this technique.
The order in which there errorlevels are given is significant,
since all the errorlevels up to the one returned will be on.
Consider the following demonstration
@echo off
find "hello" con > nul
if errorlevel==2 echo errorlevel 2 % error in search %
if errorlevel==1 echo errorlevel 1 % no match found %
if errorlevel==0 echo errorlevel 0 % match found %
If you type
peekaboo
^Z
you'll get *both*
errorlevel 1
errorlevel 0
If you type
hello
^Z
then you'll get just
errorlevel 0
Speaking of errorlevels, some novice batch users occasionally ask
for the general list of the meanings of the errorlevel values. This
question is based on a failure to grasp how errorlevels are created.
Batch files can only test their values. It is the executable
programs that can return errorlevel values. What the particular
values are, which an executable program returns, is totally
dependent on the individual program. Some programs may be able to
return a lot of different values, some none (or rather return zero
errorlevel). Perhaps this misunderstanding is based on the fact that
MS-DOS includes a number of programs, such as CHOICE.COM, FIND.EXE
and XCOPY.EXE which return errorlevels. For example MS-DOS version
6.22 XCOPY.EXE can signal with six different errorlevel values (0 to
5) depending on the outcome. For those values see "HELP XCOPY" and
select "Notes".
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 24. About redirecting a batch file's output
===========================================
Output from within a batch file is easily redirected. Consider a
batch file example.bat with the following contents
@echo This is a redirection test> test
Running "example" will produce a file "test" with
This is a redirection test
The line has an eoln (end of line: ascii 13 + 10) at the end.
Note that it often is advisable not to leave any blank in front of
the > redirection operator.
Redirecting the output that a batch produces, is more complicated.
Consider a batch file example2.bat with the following contents
@echo This is another redirection test
Running
example2 > test
will produce an empty "test" file, while the text is echoed on the
standard output. To redirect the output, you need to drive the batch
through the command interpreter command.com like this (provided that
command.com is at path or in the current directory).
command /c example2 > test
This will redirect the text to the "test" file.
There is another quirk of redirection in MS-DOS batch programming
best demonstrated by an example:
@echo off
rem This line will create an empty tmp.$$ file > tmp.$$
:: This line will not create an empty tmp.$$$ file > tmp.$$$
rem This line will cause problems: Press
:: This line will not cause problems: Press
As explained in PC Magazine Vol 12, Number 9, November 9, 1993, the
reason is that the :: is taken as a label and not processed while
the rem basically is an MS-DOS command that will be processed. The
processing will start from the redirection at the end. This is the
the also reason why redirection and the MS-DOS FOR command will
cause problems. (See the entry "For loop and redirection quirks".)
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 25. How can I test if my batch has sufficient environment space?
================================================================
If your batch utilizes environment variables there is a possibility
that you run out of environment space. If you get an "Out of
environment space" message the well-known trick to increase your
environment space by using shell configuration in config.sys:
Example: shell=c:\bin\command.com c:\bin /e:1024 /p
A perhaps less-known trick is that you can test in advance if your
batch will run out of environment space. Below is an example showing
you how to test if you have an additional 32 bytes of environment
space still available for your batch:
@echo off
set test_=12345678901234567890123456789012
if "%test_%"=="12345678901234567890123456789012" goto _yes
echo Insufficient environment space
goto _out
:_yes
echo Sufficient environment space
set test_=
rem Whatever you wish to do
:_out
To test more extensively you can use
@echo off
for %%f in (a b c d e f g h i j k l m n o p q r s t u v x y z)
do set %%f=12345678901234567890123456789012345678901234567890
set
echo "%z%"
if "%z%"=="12345678901234567890123456789012345678901234567890" goto _yes
echo Insufficient environment space
goto _out
:_yes
echo Sufficient environment space
:_out
Note! The "for" and "do" should go on the same line but have been
wrapped for legibility because of the right margin.
If you want to know what your initial environment size is, you
can use a program like SYSINFO.EXE from
148195 May 17 1998 ftp://garbo.uwasa.fi/pc/ts/tsutil44.zip
Timo's 1st utility set (sysinfo,dirw,dtetimal,timelog,...)
or whatever is the current version number of the package.
If you have a batch where getting it right is critical, it is
advisable to test for the environment space sufficiency. The sample
batch below describes the principle
@echo off
set critical_=whatever
if not "%critical_%"=="whatever" goto _nospace
echo Rest of the batch, no problem
goto _out
::
:_nospace
echo Warning: Out of environment space, batch terminated
::
:_out
set critical_=
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 26. Is there a simple trick to "disable" or hide a drive?
=========================================================
It you wish temporarily disable a drive use the subst command for
example as follows
@echo off
md c:\none
subst d: c:\none
To enable it again use
@echo off
subst d: /d
rd c:\none
A warning. This advice is for vanilla MS-DOS only. If you have
Windows it is highly inadvisable to use the SUBST command.
In ftp://garbo.uwasa.fi/pc/ts/ts5dos11.zip there is program
DRIVEOFF.EXE which can be used to disable/enable a drive. It
requires at least MS-DOS version 5.0.
Directories are much easier. You can hide a directory with the
standard ATTRIB +H command, just like any ordinary file.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 27. How can I send an escape sequence to the printer?
=====================================================
Here is a truly trivial trick. You cannot send escape sequences to
the printer directory from the command line, but it is quite easy to
do that from a simple batch file:
@echo ESC%1> prn
where you have to replace the ESC by the true escape character using
your preferred editor. One snag with this methods is that it imposes
a linefeed.
In this connection it is often also asked how one does enter the
escape character in a text editor. This, of course, depends on the
editor you are using. Nevertheless, with most editors you can either
enter 27 from the numerical part of the keyboard while holding down
the alt key (ALT-27). Furthermore, the combination of CTRL-P ESC is
a rather common convention in many text editors. If you are using
Windows 3.1x, one additional option is to use Character Map, located
in Accessories, to first copy the escape character to the clipboard.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 28. Is it possible to create a random string in a batch?
========================================================
I was asked on the UseNet news how to create a random string. My
reply. Please study the following example and expand on it
@echo off
echo 10 randomize(val(mid$(time$,7,2))) > tmp.bas
echo 20 open "tmp2.bat" for output as #1 >> tmp.bas
echo 30 x$ = mid$(str$(int(rnd*10000)),2) >> tmp.bas
echo 40 print #1,"@set random_=";x$ >> tmp.bas
echo 50 close #2 >> tmp.bas
echo 60 system >> tmp.bas
gwbasic tmp.bas
call tmp2
del tmp.bas
del tmp2.bat
set
Alternatively, depending on your MS-DOS version, you might have not
have GWBASIC but QBASIC. In that case use replace the eighth line
with "qbasic /run tmp.bas".
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 29. Is it possible in a batch to find out the length of a string?
=================================================================
The task of finding out the length of a string was tackled in PC
Magazine January 26, 1993 issue. The solution is my own and more
general, but naturally it has similar ingredients to the PC
Magazine's.
@echo off
set test_=Testing the length of a string
echo %test_% > len$&$&$
dir len$&$&$ | find "LEN$&$&$" > go$$$.bat
echo @echo off> len$&$&$.bat
echo set length_=%%1>> len$&$&$.bat
call go$$$
echo The length is %length_% bytes
del len$&$&$
del len$&$&$.bat
del go$$$.bat
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 30. How to obtain the MS-DOS version into an environment variable?
==================================================================
Here is the code how to do it.
@echo off
ver > go$$$.bat
echo @echo off> ms-dos.bat
echo set version_=%%2>> ms-dos.bat
call go$$$
echo Your MS-DOS version is %version_%
del go$$$.bat
del ms-dos.bat
MS-DOS 5.0 version introduced many enhancements (like the loadhigh
command, etc) and additions to the command switches (like /B and /S
to the DIR command). Therefore it is useful to be able to test
whether the batch is being run on a system that is at least MS-DOS
5.0. Below is one option for vanilla MS-DOS versions. Version 7 is
not included, because it is a non-independent Windows95 addition.
rem Establish whether MS-DOS version 5.0 or later is being used
set isver50_=
ver | find "5.0" > tmpfind.$$$
ver | find "6.0" >> tmpfind.$$$
ver | find "6.2" >> tmpfind.$$$
copy tmpfind.$$$ tmpfind1.$$$ > nul
del tmpfind.$$$
if exist tmpfind1.$$$ set isver50_=yes
if exist tmpfind1.$$$ del tmpfind1.$$$
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 31. How can I find out the number of regular files on a drive?
==============================================================
Try
@echo off
attrib /s c:\*.* | find /c "\"
The directories will not be (mis)counted as files as would with the
dir command. Besides the dir command is not recursive until MS-DOS
version 5.0.
Note that if you do this for the same drive where you reside,
you'll get one too many in the count because of the "|" pipe.
The /S switch in ATTRIB makes the command traverse also
subdirectories. The /C switch in FIND gives the number of the
matches found.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 32. How can I use a batch to augment line numbers to my text file?
==================================================================
Occasionally it might be useful to put line number to a text file.
Here is an example how to do it with MS-DOS commands only
@echo off
type YourFile.txt | find /v /n "&$&$&$123" > YourNew.txt
The parameter &$&$&$123 stands for an improbable string, since find
/v means displaying all the lines not containing it. The switch /n
means numbering the lines.
Here is an interesting, but probably a fairly useless little
twist:
@echo off
dir /b | find /v /n "&$&$&$123" | find "[20]"
It tells you which is the twentieth entry in a directory.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 33. Storing and returning to the original directory (push and pop)
==================================================================
There are several methods for (non-resident) pushing and popping the
directory by batch file techniques. In other words storing the
current directory, changing the directory in between, and then
returning to the starting directory. PUSHDIRE.BAT and POPDIRE.BAT
give one method where the current drive and directory are stored in
environment variables. The second method, displayed below, is a
direct adaptation from Jeff Prosise's column in PC Computing, March
1993, pp. 216-217. Later the trick was presented again in PC
Magazine June 14, 1994, Vol. 13, No. 11, p. 357. The method is a
very clever utilization of the prompt system. An example
illustrates.
@echo off
echo @prompt cd $p$_$n:> c:\setback.bat
%comspec% /c c:\setback> c:\goback.bat
::
rem Change the drive and directory
c:
cd \dos
echo The current directory is
cd
rem Do whatever you wish to do there
pause
::
rem Go back to the original drive and directory
call c:\goback
echo Now back in the original directory
cd
::
rem cleanup
if exist c:\setback.bat del c:\setback.bat
if exist c:\goback.bat del c:\goback.bat
A2: Tom Lavedas posted in news:alt.msdos.batch "I think the best
way to get the current directory's name into the environment is to
use something like this ...
@echo off
echo @prompt set CurrentLoc=$p$_ > {tempA}.bat
%comspec% /e:2048 /c {tempA}.bat > {tempB}.bat
for %%v in ({tempB}.bat del) do call %%v {temp?}.bat
This approach extracts the information from the PROMPT command's
output, making use of that statement's dollar sign equivalences."
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 34. Enticing the current date into an environment variable
==========================================================
Like in the item "Storing and returning to the original directory"
there are more than one way of doing this. One method is indicated
in the item "How to run a batch once a week". The other (again)
utilizes the prompt:
@echo off
echo @prompt set date_=$d> c:\tmp$$$.bat
%comspec% /c c:\tmp$$$> c:\tmp2$$$.bat
call c:\tmp2$$$
echo %date_%
del c:\tmp$$$.bat
del c:\tmp2$$$.bat
If you look at your MS-DOS manual for the prompt special $ codes
(like $d) that you can use in the prompt, you'll see that this
method opens quite a number of possibilities of putting information
into environment variables. Exercise: Put the current weekday into
an environment variable. Hint: Apply $d and $h.
A second method is given below. In this alternative the date is
stored in the %date_% environment variable in the eight-character
format. It also gets the current time.
@echo off
::
rem Create a temporary batch file to set the date
echo @echo off> date$$$$.bat
echo set date_=%%3>> date$$$$.bat
echo set time_=%%4>> date$$$$.bat
::
rem Create another batch which executes the first
dir date$$$$.bat | find "DATE$$$" > tmp$$$.bat
call tmp$$$
::
rem Delete the temporary batch files
if exist tmp$$$.bat del tmp$$$.bat
if exist date$$$$.bat del date$$$$.bat
::
rem Test it
echo %date_%
echo %time_%
For a third method that puts the date into the %date_% environment
variable see e.g. the item "How can I backup from the current
directory files made today?" of this batch FAQ collection. It
produces the ten-character format.
Let's return to the first method. Batch savant Tom Lavedas often
uses the following kind of style.
@echo off
echo @prompt set Date=$d$_set Time=$t$h$h$h> {a}.bat
%comspec% /e:2048 /c {a}.bat > {b}.bat
for %%v in ({b}.bat del) do call %%v {?}.bat
echo The date is %Date% and the time is %Time%
Let's study closer the logic of this batch. There is much to learn
from the details.
1) @echo off
- turns off echoing the commands on the screen
2) echo @prompt set Date=$d$_set Time=$t$h$h$h> {a}.bat
- creates auxiliary batch {a}.bat and puts there
@prompt set Date=$d$_set Time=$t$h$h$h
- $d displays the current date in the prompt
- $_ enters a linefeed in between
- $t displays the current time in the prompt
- $h$h$h deletes the last three characters,in this case the
superfluous hundreds of the second)
3) %comspec% /e:2048 /c {a}.bat > {b}.bat
- runs {a} and put the results into another auxiliary batch
{b}.bat whose contents will be e.g.
set Date=Sat 11/07/1998
set Time=14:07:03
- /e:2048 reserves (usually) enough environment space
- /c tells the command interpreter to exit after performing
the task. This avoids multiple shells.
4) for %%v in ({b}.bat del) do call %%v {?}.bat
- this is "shorthand" for
call {b}.bat
del {?}.bat %which deletes both {a}.bat and {b}.bat%
5) echo The date is %Date% and the time is %Time%
- displays the result
Please also see the related, further refined later item "How get
today's date into a six-character environment variable?".
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 35. A tip for power users. Identifying the individual PC.
=========================================================
In cases of some batches it is useful to identify the PC the batch
is run on. For example I have several different PCs myself and
occasionally I need to differentiate between them. The solution is
really trivial. Set an environment variable in the autoexec.bat to
designate the PC. I use a variable pcid_ for this purpose. An (old)
outline batch illustrates.
@echo off
if "%pcid_%"=="" goto _none
goto %pcid_%
:dell
echo Dell 325N laptop, do whatever
goto _out
:trifu
echo Trifunic 386 desktop, do whatever
goto _out
:karvi
echo "Garfunkel" Pinus 486 desktop, do whatever
goto _out
:_none
echo PC not identified, do whatever
:_out
For example in the autoexec.bat of my DELL 325N laptop I have
set pcid_=dell
You'll see this identification trick used e.g. in the BOOT.BAT batch
of the collection at hand.
Another, similar trick I employ is standardizing the ram disk
reference by applying in my AUTOEXEC.BAT e.g.
set ram=m
This I can always refer in my batches as %ram% to the ram disk
letter irrespective of which of my PCs I am using. You'll see this
trick used in some of the individual batch files of this collection.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 36. For loop and redirection quirks
===================================
A question from the Usenet newsgroups news:comp.os.msdos.misc and
news:comp.os.msdos.programmer:
> I am using DOS 5.0 and I have the following line in my batch file:
> for %%f in (a b c d) do if exist %%f echo put %%f >> tmpfile
> where a,b,c,d are some filenames.
>
> What I expect it to do is to echo the lines
> put a
> put b
> put c
> put d
> into the file tmpfile.
>
> But what happen is after the "put a" is written to tmpfile, the rest
> of the lines will just echo to the screen, look like that the
> redirection is not working.
>
> If I take away the "if exist" everything is working fine. I found
> out every time when I use a conditional statement with redirection,
> it will only redirect the first time, the rest will echo to the
> screen.
>
> Is it the for loop cannot be mixed with the conditional statement
> and the redirection?
Yes, it can be mixed, but not so simply in this case. Use the
following batch
@echo off
del tmpfile
for %%f in (a b c d) do if exist %%f call auxil %%f
where auxil.bat contains
@echo off
echo put %1>> tmpfile
I'll be darned if I know why :-).
In fact it is possible to do this with a single batch by employing
the following method described in an earlier item
@echo off
echo @prompt echo put %%%%1$g$g tmpfile> tmp$$$.bat
%comspec% /c tmp$$$> auxil.bat
if exist tmpfile del tmpfile
for %%f in (a b c d) do if exist %%f call auxil %%f
del tmp$$$.bat
del auxil.bat
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 37. Is it possible to traverse a directory tree with a batch?
=============================================================
Traversing it straight up is relatively easy as can be seen from
this example.
@echo off
:_loop
dir/w
if not exist ..\nul goto _out
cd ..
goto _loop
:_out
Going recursively down through a directory and its subdirectories is
very complicated. Yet it can be done if you have MS-DOS 5.00 or
beyond. The SWEEP.BAT batch accompanying tsbat*.zip demonstrates
how. The method is, however, too difficult to be of real practical
importance. It is getter to use an auxiliary program for sweeping,
like TARGET.EXE ftp://garbo.uwasa.fi/pc/filefind/target15.zip or
SWEEP.COM from ftp://garbo.uwasa.fi/pc/pcmagvol/vol4n24.zip.
Especially TARGET.EXE is a very versatile tool.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 38. It it possible to echo the redirection symbol in a batch?
=============================================================
In certain situations would be useful to be able echo the
redirection symbol rather than have its perform its redirection
function. For example your batch file might have a help line like
this
echo The line to customize is "echo dir/w %%%%3\%%2 >> %%new_%%"
As you see the double quotes pre-empt the redirection. If you left
them out, the line would result create a file %NEW_% containing
"The line to customize is echo dir/w %%3\%2".
Contrary to Unix, \ cannot be used to cover the special meaning
of a symbol. As explained in the item "The quote character %" the %
sign, can as is demonstrated above by the %% pairs. But %> does not
take precedence over the redirection.
Tom Lavedas posted a useful example in news:alt.msdos.batch which
shows additional trick in the the echoing to the screen. The
solution goes like this:
@echo off
echo "^HThis is a pair of greater than signs >>"^H.
In the above the ^H means the backspace character which you can
input e.g. in MS-DOS Edit by entering ctrl-P H . An additional
aspect of this solution is that the last ^H must be followed by at
least one character. Otherwise the last " will be sent to the
console.
Q2: I want to send the character | to a batch to form a batch file.
For instance when I try the following
echo dir /w /p | find "Vol" >>file.bat
I get a file.bat file that contains nothing. How can I solve this?
A2: This problem can be solved by using QBASIC which comes with
e.g. MS-DOS version 6.22. Below is the batch that does what is being
asked for. The crucial trick is to use variables for the characters
which batches cannot redirect. Below b$ contains |, i.e. the ASCII
character 124. (q$ contains the quote " character.)
@echo off
> tmp$$$.bas echo LET q$ = CHR$(34)
>> tmp$$$.bas echo LET b$ = CHR$(124)
>> tmp$$$.bas echo OPEN "file.bat" FOR OUTPUT AS #1
>> tmp$$$.bas echo PRINT #1, "@echo off"
>> tmp$$$.bas echo PRINT #1, "dir /w "; b$; " find "; q$; "Volume"; q$
>> tmp$$$.bas echo CLOSE #1
>> tmp$$$.bas echo SYSTEM
qbasic /run tmp$$$.bas
del tmp$$$.bas
P.S. The /w switch and especially the /p switch in the question are
superfluous.
There also is a prompt-base solution as pointed out by Tom Lavedas:
"It can also be solved using the characteristics of the PROMPT
command, specifically the dollar sign substitution character '$B',
something like this ...
echo @prompt dir /w /p $b find "Vol" > {t}.bat
%comspec$ /e:2048 /c {t}.bat >> file.bat
del {t}.bat
BTW, I usually can find a way around needing such a construction,
often with less programming overhead."
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 39. How can I extract the file basename?
========================================
Occasionally one needs to get the file name without the extension.
Just like getting the extension from a file name using the "for %%f
in (/%exten_%)" trick, even this can be done with batch commands
only. The batch code for getting the basename has been presented by
Neil Rubenking in PC Magazine April 26, 1994, Vol. 13, No. 8, pp.
275-276. But enough is enough even with batch tricks. The logic is
getting overly complicated. One has to draw the line somewhere, stop
kidding oneself, and start using batch enhancers (external programs
to help out). I think here the limit has been reached. Hence I have
included "basename" and "basepath" programs, which you can use to
create the enhancers. They return the relevant information into an
environment variable with that name.
When you come to think of it. From one viewpoint, what else than
batch enhancers are all the external MS-DOS commands (usually) in
your C:\DOS directory?
Using basename and basepath is very easy. Below is an example
@echo off
basename r:\cmand\command.com
basepath r:\cmand\command.com
echo %basename%
echo %basepath%
You can discard the environment variable simply by applying (note
the two alternatives):
set basename=
basepath
There is also a "basexten" batch enhancer in the /pc/ts/tsbat*.zip
collection.
A batch-only solution is presented below. It owes heavily to a
posting by Ted Davis in news:alt.msdos.batch.
@echo off
::
rem Instructions
if "%1"=="" goto _usage
::
rem Create an auxiliary directory
mkdir tmpaux$$
::
rem Create an empty auxiliary file
rem > tmpaux$$\%1
::
rem Go to the auxiliary directory
cd tmpaux$$
::
rem Rename the file without extension (this is the trick!)
ren %1 *.
::
rem Get the new file name into an environment variable
for %%f in (*) do set basename=%%f
::
rem Let's test it
echo The basename is %basename%
::
rem Back to the original directory
cd ..
::
rem Delete the auxiliary file
echo.| del tmpaux$$\*
::
rem Delete the auxiliary directory
rmdir tmpaux$$
::
rem Delete the environment variable
set basename=
::
goto _end
::
:_usage
echo Usage: %0 [FileNameWithExtension]
:_end
Another batch-only alternative would be to utilize the BASIC
interpreters that come with MS-DOS.
@echo off
::
:: If no parameter is given to the batch, show its proper usage
if "%1"=="" goto _help
::
:: Prepare a QBASIC program to extract the base from a filename
:: Handle different file name types like NAME.DAT NAME and .DAT
echo LET a$="%1" > tmp$$$.bas
echo LET p = INSTR(1, a$, ".") - 1 >> tmp$$$.bas
:: Case of only extension, no basename
echo IF p = 0 THEN LET a$ = "" >> tmp$$$.bas
:: Other cases
echo IF NOT (p=-1) AND NOT (p=0) THEN LET a$ = MID$(a$, 1, p) >> tmp$$$.bas
echo OPEN "tmp###.bat" FOR OUTPUT AS #1 >> tmp$$$.bas
echo PRINT #1, "@echo off" >> tmp$$$.bas
echo PRINT #1, "set basenam_=" + a$ >> tmp$$$.bas
echo SYSTEM >> tmp$$$.bas
qbasic /run tmp$$$.bas
::
:: Call the batch created by the QBASIC program
call tmp###.bat
::
:: Demonstrate that the result is in the basenam_ environment variable
if not "%basenam_%"=="" echo The basename of %1 is %basenam_%
if "%basenam_%"=="" echo The basename of %1 is empty
goto _end
::
:_help
echo Usage %0 [FullFileName]
::
:: Cleanup
:_end
if exist tmp$$$.bas del tmp$$$.bas
if exist tmp###.bat del tmp###.bat
set basenam_=
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 40. A batch to put user input into an environment variable
==========================================================
This definitely must be the neatest batch programming trick I have
ever seen. It is an adaptation of the batch published in Neil J.
Rubenking's User-to-User column in PC Magazine June 27, 1995, Vol.
14, No. 12, pp. 247-248. It is based on an idea by Tom Lavedas. It
will remedy the biggest (alleged) flaw in MS-DOS batch programming,
that is getting user input without any external programs. My
adaptation puts a simple word input into the INPUT_ environment
variable. The original inputs a whole sentence, but it is more
complicated. A single word (or a single letter) input is what is
usually sufficient in batch programming. The essence of the trick,
of you want to study it carefully to understand it, is in the fact
that the time command outputs the word "Enter" which features as an
auxiliary batch to be run by the SETINPUT.BAT below. An MS-DOS
version 3.3 or later is required.
@echo off
rem INPUT.BAT
echo This will copy your input to the environment variable INPUT_
echo Give your input:
fc con nul /lb1 /n | time | find " 1: "> setinput.bat
echo @echo off> enter.bat
echo set input_=%%4>> enter.bat
call setinput
del setinput.bat
del enter.bat
echo The value of INPUT_=%input_%
The /LB switch in the above with value 1 sets to one the number of
lines for the internal line buffer. The /N switch "displays the line
numbers during an ASCII comparison".
For more on this approach see Tom's WWW page "Input in a Running
Batch File" http://www.deltaelectronics.com/tglbatch/input.htm.
This is also a suitable spot to show the usage of the MS-DOS
CHOICE.COM input command with the following example. Note that the
order of the errorlevel tests is significant and should be retained
in the order used below.
@echo off
choice /c:ync /t:c,10 "Respond within 10 seconds (else C is assumed) "
if errorlevel 3 goto _cancel
if errorlevel 2 goto _no
if errorlevel 1 goto _yes
if errorlevel 0 goto _break
echo Error! This should not happen.
goto _end
:_break
echo Break was pressed
goto _end
:_yes
echo Y was pressed
goto _end
:_no
echo N was pressed
goto _end
:_cancel
echo C was pressed, or no response within 10 seconds
:_end
For an explanation of the CHOICE.COM switches apply "HELP CHOICE" if
you have MS-DOS 6.22.
A2: It is instructive to note that batches often can be improved
since there is some hitch. In this case Larry Weiss observed that
"If the user enters only the Return-key, then the bat file will
reset the system time to 1:00 am. There is no warning about this
unfortunate side-effect. That bat file can be re-written to use
'date' instead of 'time' (replacing the reference to %%4 with %%5)
as:
@echo off
rem INPUT.BAT
echo This will copy your input to the environment variable INPUT_
echo Give your input:
fc con nul /lb1 /n | date | find " 1: "> setinput.bat
echo @echo off> enter.bat
echo set input_=%%5>> enter.bat
call setinput
del setinput.bat
del enter.bat
echo The value of INPUT_=%input_%
With those changes, there is no unexpected disturbance of either the
date nor time when no input is provided."
A3: Another, easier approach to this problem is using a QBASIC
solution. QBASIC comes with e.g. MS-DOS version 6.22.
@echo off
::
:: Build a QBASIC program to a file tmp$$$.bas
> tmp$$$.bas echo PRINT "Give your input";
>> tmp$$$.bas echo INPUT a$
>> tmp$$$.bas echo OPEN "tmp###.bat" FOR OUTPUT AS #1
>> tmp$$$.bas echo PRINT #1, "@echo off"
>> tmp$$$.bas echo PRINT #1, "set input=";a$
>> tmp$$$.bas echo CLOSE #1
>> tmp$$$.bas echo SYSTEM
::
:: Run the QBASIC program prepared in the above
qbasic /run tmp$$$.bas
::
:: Call the tmp###.bat batch created by the tmp$$$.bas QBASIC program
call tmp###.bat
::
:: Delete the auxiliary files
del tmp$$$.bas
del tmp###.bat
::
:: Test the result
echo Your input was %input%
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 41. How can I get the last replaceable parameter given to a batch?
==================================================================
As we know, batch files can use the so-called replaceable parameters
from %0 to %9. It is easy to get the first parameter in a batch
call. It is %1. (%0 gives the batch name). But what about getting
the last parameter when you do not know in advance how many
parameters the call has. Below is the code. It puts the last
parameter in the environment variable NF_.
@echo off
set nf_=
:_loop
if "%1"=="" goto _end
set nf_=%1
shift
goto _loop
:_end
rem Let's test the result
if not "%nf_%"=="" echo %nf_%
if "%nf_%"=="" echo No parameters were given to the batch
Note a catch. After you apply the above, you no longer can access
the original parameters. If you need them later in the batch, you
have to store them at the outset of the batch file, e.g. like this
set bname_=%0
set a_=%1
set b_=%2
set c_=%3
John Savage points out that the code for getting the last parameter
can be made simpler:
@echo off
:_loop
shift
if not "%1"=="" goto _loop
echo last parameter is "%0"
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 42. Creating an empty file if the file does not already exist
=============================================================
@echo off
if exist testfile goto _nocreate %Don't destroy an existing file%
rem > testfile
:_nocreate
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 43. How can I change or remove the disk volume serial number?
=============================================================
Since version 4.0 the disk serial number was added to MS-DOS. When
you format a disk is it given a number like 4132-1DFF. It is
possible to change that information with an innovative batch file
alone. The batch by Bruce W. Shumway can be found in the PC Magazine
April 23, 1996, Vol. 15 No. 8, pp. 221-222. There also is a program
SETSER.EXE "Set the disk's serial number" by yours truly in the
ftp://garbo.uwasa.fi/pc/ts/ts5dos11.zip collection.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 44. How to pause in a batch for a preset number of seconds?
===========================================================
You can use the MS-DOS CHOICE.COM command for the purpose as the
example below demonstrates
@echo off
echo Testing a delay, starting at ...
echo.| time | find /v "new"
choice /c:. /t:.,5 /n Pausing for five seconds
echo ending at ...
echo.| time | find /v "new"
The choice command was introduced with MS-DOS 6. If you have an
earlier MS-DOS version you can use my similar CHOOSE.EXE from
ftp://garbo.uwasa.fi/pc/ts/tsutlf15.zip.
For pauses longer than 99 seconds see the item #64. For better
understanding the CHOICE parameter values, see the end of item #40.
Tom Lavedas points out that if one uses
type nul | choice /c:. /t:.,5 /n Pausing for five seconds
"The piping of the output from the TYPE command into CHOICE acts to
defeat keyboard entry for the wait period."
Also see the later item "How can I write a "SLEEP" command to pause
for a certain time?" for more on this question.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 45. Where can I find a program to compile batches into COMs or EXEs?
====================================================================
Since this question is so frequently asked I'll include an answer
into my 1batfaq.txt information file. From Garbo program archive's
MS-DOS index file ftp://garbo.uwasa.fi/pc/INDEX.ZIP we can readily
locate the following files. Personally, I am dubious about batch
compilers and their complications. In my opinion, if one wants
distribute executables, it is much better to use a genuine
programming language like Turbo Pascal or C. I prefer batches in
their regular source format.
37419 Aug 10 1991 ftp://garbo.uwasa.fi/pc/pcmagutl/bat2ex15.zip
bat2ex15.zip Compile batch files to be executables, PC-Mag update
51299 Oct 31 1994 ftp://garbo.uwasa.fi/pc/batchutil/tbt324.zip
tbt324.zip TurboBAT Batch File Compiler, Foley Hi-Tech Systems
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 46. How can I test whether a disk is empty or not?
==================================================
This question is best answered by an annotated batch source:
@echo off
rem Provide help if no parameter is given.
if "%1"=="" goto _usage
rem Check that the input syntax was acceptable.
for %%f in (a b A B) do if "%1"=="%%f" goto _label1
goto _usage
rem See if "bytes free" appears in the directory listing as it will
rem if and only if there are files in the directory.
:_label1
dir %1:\ /s | find "bytes free" > found.$$$
rem If "bytes free" was not found found.$$$ file will be empty.
rem An empty file will not be copied.
copy found.$$$ notempty.$$$ > nul
rem If found.$$$ was empty is was not copied, use this fact to test.
if exist notempty.$$$ echo Disk %1: is not empty
if not exist notempty.$$$ echo Disk %1: is empty
rem Delete the auxiliary files.
if exist found.$$$ del found.$$$
if exist notempty.$$$ del notempty.$$$
goto _out
:_usage
echo Usage: %0 [DriveLetter]
echo e.g. %0 A
echo Put no colon (:) after the DriveLetter!
:_out
The volume where you drive this from must not be write protected.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 47. How can I run a different batch depending on the weekday?
=============================================================
@echo off
::
rem Let's take care of everything by a single batch file.
rem First prepare a batch for each day. For brevity let's prepare
rem them for Monday and Tuesday days only.
::
echo echo It is Monday today and whatever else you may wish to do>mon.bat
echo echo It is Tuesday today and whatever else you may wish to do>tue.bat
::
rem The date command produces output like
rem Current date is Tue 27/08/1996
rem Enter new date (dd-mm-yy):
::
rem Utilize this fact by making a batch file tmp$$$.bat which in turn
rem runs the batch which is the third parameter (%3) of current.bat
rem (Tue.bat in the above).
echo.| date | find "Current">tmp$$$.bat
echo call %%3>current.bat
call tmp$$$.bat
::
rem Let's delete the tmp$$$.bat and current.bat files.
if exist current.bat del current.bat
if exist tmp$$$.bat del tmp$$$.bat
::
rem Since this was only a test, let's delete all the daily files, too.
if exist mon.bat del mon.bat
if exist tue.bat del tue.bat
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 48. Can one put line numbers into a file with just batch commands?
==================================================================
The essence of this item is from postings in news:alt.msdos.batch
by John Savage. The trick is
FC /N nul file.txt > file2.txt
The number of lines is limited to a hundred lines. You can increase
that to a maximum of 222 lines using
FC /N /LB222 nul file.txt
As you see, there is some redundancy in this batch FAQ, since there
are so many items. This question was already tackled in item #32 but
using a different (a FIND) method.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 49. How can I backup from the current directory files made today?
=================================================================
Here is the trick using XCOPY tested on a PC running MS-DOS 5.0.
@echo off
rem Get the date into an environment variable
echo.| date | find "Current" > tmp$$$.bat
echo set date_=%%4> current.bat
call tmp$$$
if exist tmp$$$.bat del tmp$$$.bat
if exist current.bat del current.bat
::
rem Copy the files created or updated today
xcopy *.* a:\ /D:%date_% /P /V
if errorlevel 0 goto _out
echo An XCOPY error has occurred
::
:_out
set date_=
The country-dependent XCOPY parameter /D:date copies files modified
on or after the given date. The /P prompts for confirmation. The /V
parameter sets copy verification on.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 50. How can I traverse all files of a directory in a batch?
===========================================================
See REPEAT.BAT of my TSBAT*.ZIP batch files collection.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 51. How can I step through a batch a command at a time to debug it?
===================================================================
This question is answered by MS-DOS "HELP COMMAND". Take a look. The
essence of the method is this: "command /y /c mybatch.bat". This
lets you traverse your batch one command at a time. Another trick is
to use REM and GOTO commands to help locate when the error occurs
and when not. It has the advantage of letting you choose the parts,
which you wish to concentrate on. Yet another method is to place
PAUSE commands near the problem spots to identify which line causes
the error.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 52. How to display all files made or updated on a day or today?
===============================================================
To find the answer please study DATEDIR.BAT.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 53. How can I make a list of all my files and locate a certain file?
====================================================================
Let's assume that you have three three partitions, the drives C, D
and E. To make an ordered list of all your files you can apply e.g.
@echo off
if exist myfiles.lst del myfiles.lst
for %%f in (c d e) do dir /w /o:en /s %%f:\*.* >> myfiles.lst
To be able to find a certain file add
edit m:\myfiles.lst
The /W parameter displays the results of DIR in a wide format. The
/O:EN sort the results by extension and name. The /S parameter
traverses also all the subdirectories.
Another option which lists all your files, this time with with paths
included, but without the ordering, is
@echo off
if exist myfiles.tmp del myfiles.tmp
for %%f in (c d e) do chkdsk /v %%f: >> myfiles.tmp
type myfiles.tmp | find "\" | find /v "Directory " > myfiles.lst
del myfiles.tmp
To be able to find a specific file on your harddisk add
type myfiles.lst | find /i "%1"
The FIND parameter /V displays the lines where the target does not
exist. The /I parameter specifies a non-case sensitive search.
The same approach can be extended to find e.g. all the hidden files
on your harddisk. This is how it goes
@echo off
if exist myfiles.tmp del myfiles.tmp
for %%f in (c d e) do attrib /s %%f:\*.* >> myfiles.tmp
find "H " < myfiles.tmp
find "HR " < myfiles.tmp
del myfiles.tmp
The /S switch in ATTRIB means scanning also all the subdirectories.
I regularly make three complementary kinds of logs of all the files
I have on my harddisk. Below is a useful batch for the task. A
C:\DIRLOG directory is assumed to exist.
@echo off
rem Help if necessary
if "%1"=="" goto _help
::
rem Check that the PC has an identification
if "%pcid_%"=="" goto _nopcid
::
rem Which drive will we list
set drive_=%1
if not exist %drive_%:\nul goto _nodrive
::
rem Make a list of the files on the drive
c:
cd \dirlog
echo on
dir /w /o:en /s %drive_%:\*.* > c:\dirlog\%pcid_%%drive_%.hak
tree %drive_%:\ > c:\dirlog\%pcid_%%drive_%.tre
chkdsk /v %drive_%: > c:\dirlog\%pcid_%%drive_%.pth
@echo off
set drive_=
goto _out
::
:_nopcid
echo Environment variable PCID_ identifying your PC is not set, exiting
echo Set it in your autoexec.bat
goto _out
::
:_nodrive
echo Drive %drive_%: not found
set drive_=
goto _out
::
:_help
echo Usage: %0 [DriveLetter]
::
:_out
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 54. How can I tell if a batch is running in a Windows dosbox?
=============================================================
One can utilize the fact that under Windows the "windir" environment
variable is set. However, since it is in lower case, the status must
be tested in a roundabout way. I have tested this code on Windows
3.11 only.
@echo off
set | find "windir=" > wintmp$$.$$$
copy wintmp$$.$$$ winbox$$.$$$ > nul
if exist winbox$$.$$$ echo Running under Windows
if not exist winbox$$.$$$ echo Not running under Windows
if exist wintmp$$.$$$ del wintmp$$.$$$
if exist winbox$$.$$$ del winbox$$.$$$
To find out the directory from which Windows was launched see Tom
Lavedas's http://www.zdnet.com/pcmag/pclabs/solution/uu1506c.htm.
-From: Gerry Kroll
-Newsgroups: alt.msdos.batch
-Subject: Re: Is DOS Running
-Date: 31 Jan 1998 02:48:44 GMT
-Organization: Public Works & Government Services (Gov't of Canada)
The above requires a small explanation:
FIND from DOS versions before 6.0 did not set an ERRORLEVEL to
indicate the success or failure of the search.
FIND, when used as shown above, produces *no* output when the
file being inspected does not contain any lines with the search
object. If the output of FIND is sent to a file and the search
object doesn't exist (the search fails), the result is a zero-length
file.
You can't test for a zero-length file directly; what CAN be done
is to use COPY. COPY will not copy a zero-length file (I hope they
NEVER fix that!!). Thus, if the copy of the original file exists,
the original file must have had a length other than zero. Therefore,
if the copy exists, the output of FIND consisted of at least one
line, and therefore the search object exists in the original file
being inspected through FIND.
The whole thing is a LOT simpler if you have DOS 6.0 or higher.
Just run the FIND and test for the correct ERRORLEVEL. Type HELP
FIND at the DOS prompt.
Regards,
Gerry Kroll, PWGSC, Government of Canada
Timo's addition: Under MS-DOS 6+ the batch could be written as given
below. Note the required order of testing the errorlevels.
@echo off
set | find "windir=" > nul
if errorlevel==1 goto _1
if errorlevel==0 goto _0
:_0
echo Running under Windows
goto _out
:_1
echo Not running under Windows
:_out
A2: Another method is to make a WIN.BAT file at path before the
Windows directory and set an environment variable to indicate that
Windows has been loaded. It is also a good usage to reset the prompt
to show you when you are in a dosbox.
@echo off
set prompt_=%prompt%
set prompt=%prompt_%[win]
set win_=winbox
c:\windows\win
set prompt=%prompt_%
set prompt_=
set win_=
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 55. How can a test that there is a disk in a floppy disk drive?
===============================================================
The code is given below. It owes much to a posting on the Usenet
news by the batch programming wizard Tom Lavedas with personal
touches and commentary from yours truly.
@echo off
if "%1"=="" goto _help
ctty nul
%comspec% /f /c dir %1: | find "Directory of "
ctty con
if errorlevel==0 if not errorlevel==1 goto _isready
echo Drive %1 is NOT ready
goto _end
::
:_isready
echo Drive %1 is ready
goto _end
::
:_help
echo Usage %0 [DriveLetter]
::
:_end
Let's take a closer look at this instructive batch.
1) "@echo off" turns off echoing on the subsequent lines. The @
prevents echoing of the command itself.
2) If no parameter was given "if "%1"=="" goto _help" presents the
required syntax.
3) "ctty nul" alters the default input device from the default
con(sole) to nothing preventing any user input.
4) "%comspec% /f /c dir %1:" call the directory command via the
command interpreter. The undocumented /f switch avoids the
"Abort, Retry, Fail?" input requirement if the disk is not
present. The /c switch specifies that the command interpreter is
to exit immediately after performing the task. Else there
multiple shelling would pile up that would need a corresponding
exit. The "%comspec%" environment variable specifies where the
COMMAND.COM file is located. The "%comspec%" environment
variable is set by a shell= line in the CONFIG.SYS file.
5) | find "Directory of " pipes the result of "dir" to the find
command. If a disk is present in the drive the string will be
found and "find" returns an errorlevel of 0. Else it will return
a higher errorlevel value.
6) "ctty con" turns input back to the console i.e. the keyboard.
7) "if errorlevel==0 if not errorlevel==1 goto _isready" test
whether the value of the errorlevel is zero. If it is then the
batch jumps to the label ":_isready". Note that logically the
part "if errorlevel==0" is superfluous. It is there how a
specific errorlevel value (zero) can be tested for. For more on
testing the errorlevel see LEVEL.BAT.
8) Most of the rest of the batch is obvious and does not need extra
comments. In "echo Usage %0 [DriveLetter]" the %0 returns with
path the name of the batch being run.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 56. Could you please solve this problem for me with a batch?
============================================================
There is a fine line between asking for advice and trying to exploit
others with free consultation requests. It is not uncommon to see
Usenet news postings, or even email, where a user asks to have
his/her particular problem programmed for him/her. I do not consider
this fair nor quite proper. The purpose of FAQs like the current one
is to provide the readers with batch usage information and useful
tools, not to do their work on their behalf for free.
Requests for homework assignment solutions are another phenomenon
which regularly occur on some programming newsgroups on the Usenet
news. It is not conductive to learning to help students to cheat on
their homework assignments. Here is what you, a student, should do.
First study. Start the assignment yourself. Try your very best to
solve your assignment. Then, if you really get stuck after having
tried very very hard yourself, come back on the appropriate Usenet
newsgroup with specific questions and the code which you have
devised so far. That kind of help will usually be forthcoming. But
please do not email such questions. We are not your individual
tutors.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 57. How can I make a loop that is repeated a preset number of times?
====================================================================
The solution below, edited only in the slightest to make the style
compatible, was posted to Usenet newsgroup news:alt.msdos.batch by
Ted Davis. Ted is a major contributor in the newsgroup with very
neat batch solutions.
@echo off
set count_=
set target_=!!!!!
:_loop
echo This is one pass %count_%
set count_=%count_%!
if "%count_%"=="%target_%" goto _endloop
goto _loop
:_endloop
set count_=
set target_=
The URL http://gearbox.maem.umr.edu/~batch/intrin1.htm#bang has more
on this issue.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 58. How can I display the contents of the memory?
=================================================
Here is the outline
@echo off
echo d 0000:0000 > infile.dbg
echo d 0000:0080 >> infile.dbg
echo d 0000:0100 >> infile.dbg
echo d 0000:0180 >> infile.dbg
echo d 0000:0200 >> infile.dbg
echo q >> infile.dbg
debug < infile.dbg | more
del infile.dbg
A detail. In the PC memory addressing conventions the line
echo d 0000:0180 >> infile.dbg
is equivalent to line
echo d 0010:0080 >> infile.dbg
The memory addresses are in hexadecimal. E.g. the above (180H) is
384 in decimal.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 59. How get today's date into a six-character environment variable?
===================================================================
This fairly difficult task has become quite a frequently asked
question. The demonstration batch below does the trick. It assumes
that the date is of the format "Current date is Mon 13/04/1998",
i.e. that the date separator is a slash (but this is easy to
customize). Perhaps the most common application of getting the date
into the 980413 format is making date-dependent file names, such as
e.g. TS980413.TXT . The main trick that the batch below uses is
making several passes by calling itself in the for statements. That
could be avoided, but the batch would become very long if the for
statements were written out to avoid the need of recursion.
@echo off
rem Determine which pass we are making
if "%1"=="" goto _1stpass
if "%2"=="" goto _wdpass
if "%3"=="" goto _daypass
if "%4"=="" goto _mmpass
rem Extract the year
find "/19%4" tmp$$$.$$$ > nul
if not errorlevel==1 if errorlevel==0 set yearnr_=%4
find "/20%4" tmp$$$.$$$ > nul
if not errorlevel==1 if errorlevel==0 set yearnr_=%4
goto _end
rem Extract the month
:_mmpass
find "/%3/" tmp$$$.$$$ > nul
if not errorlevel==1 if errorlevel==0 set monthnr_=%3
goto _end
rem Extract the day
:_daypass
find " %2/" tmp$$$.$$$ > nul
if not errorlevel==1 if errorlevel==0 set daynr_=%2
goto _end
rem As an extra demo also get the name of the weekday
:_wdpass
find "%1" tmp$$$.$$$ > nul
if not errorlevel==1 if errorlevel==0 set weekday_=%1
goto _end
rem Put the date in a file so that find can be applied on it
:_1stpass
echo.|date > tmp$$$.$$$
rem Go through all the alternatives. Note the dummy x parameters
rem to determine which part of the date is being processed
for %%d in (Sun Mon Tue Wed Thu Fri Sat) do call %0 %%d
for %%d in (01 02 03 04 05 06 07 08 09 10) do call %0 x %%d
for %%d in (11 12 13 14 15 16 17 18 19 20) do call %0 x %%d
for %%d in (21 22 23 24 25 26 27 28 29 30 31) do call %0 x %%d
for %%d in (01 02 03 04 05 06 07 08 09 10 11 12) do call %0 x x %%d
for %%d in (97 98 99 00 01 02) do call %0 x x x %%d
rem Show the results
echo %weekday_%
echo %yearnr_%%monthnr_%%daynr_%
rem Clean up
set weekday_=
set daynr_=
set monthnr_=
set yearnr_=
del tmp$$$.$$$
:_end
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 60. How can I find and copy the files updated today in a directory?
===================================================================
To solution with batch commands only is given below. Specialized
programs, however, are more convenient and flexible. For example
ftp://garbo.uwasa.fi/pc/filecopy/pcopy93.zip.
@echo off
::
rem Put the current date into an environment variable "datenow_"
echo.| date | find "Current" > tmp$$$.bat
echo set datenow_=%%4> current.bat
call tmp$$$
::
rem Clean up a bit
del current.bat
del tmp$$$.bat
::
rem Copy all the files in a directory updated today to a floppy
::
rem Clean up some more
xcopy *.* a:\ /-y /p /d:%datenow_%
set datenow_=
The XCOPY switch /-Y means that your permission is asked before
overwriting any file. The switch /P ask before copying any file. The
/D: switch tell that files made at %datenow_% (or later) are to be
copied.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 61. How can I test in a batch whether a TSR program has been loaded?
===================================================================
Here is an example that does that. The example tests if the SMARTDRV
is resident in memory, but it could be any TSR.
@echo off
mem /c | find "SMARTDRV" > nul
if errorlevel==2 goto _nofind
if errorlevel==1 goto _nofind
echo SMARTDRV is loaded
goto _end
:_nofind
echo SMARTDRV is not loaded
:_end
Another similar, even better way of doing the same thing is
@echo off
mem /m smartdrv | find "is using the following memory" > nul
if errorlevel==2 goto _nofind
if errorlevel==1 goto _nofind
echo SMARTDRV is loaded
goto _end
:_nofind
echo SMARTDRV is not loaded
:_end
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 62. Putting the current drive letter into an environment variable.
==================================================================
The trick is the same as in the item #18 including the trick how to
put the current directory into an environment variable.
@echo off
echo @echo off> volume.bat
echo set getdrv_=%%3>> volume.bat
dir | find "Volume"> go.bat
call go
if exist volume.bat del volume.bat
if exist go.bat del go.bat
::
rem show that we got it
echo %getdrv_%
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 63. How can I extract the drive letter from a full file path?
=============================================================
Here goes, assuming a full path has been given! Does not work on
write protected drives.
@echo off
if "%1"=="" goto _usage
::
rem Get the current drive letter
echo @echo off> volume.bat
echo set origdrv_=%%3>> volume.bat
dir | find "Volume"> go.bat
call go
if exist volume.bat del volume.bat
if exist go.bat del go.bat
::
rem Change to the drive where the program is (trick due to Tom Lavedas)
rem The \ makes to change the drive instead of running the program
%1\
::
rem Get the drive letter after the change
@echo off
echo @echo off> volume.bat
echo set getdrv_=%%3>> volume.bat
dir | find "Volume"> go.bat
call go
if exist volume.bat del volume.bat
if exist go.bat del go.bat
::
rem Go back to the original drive
%origdrv_%:
set origdrv_=
::
rem Show the result
echo %getdrv_%
goto _end
::
:_usage
echo Usage: %0 [FullPath, e.g. C:\DOS\ANSI.SYS]
:_end
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 64. How can I write a "SLEEP" command to pause for a certain time?
==================================================================
If the delay you want is no more than 99 seconds the answer is
fairly simple. All you need is the CHOICE command with appropriate
options. For example the following batch pauses for ten seconds. You
can, if you wish, break the wait by pressing the key b.
@echo off
choice /cb /t:b,10 /n > nul
rem ^ ^ "use b as the a break the wait key"
For longer waits a loop is needed. The following batch sets a ten
minute wait. Remove the line "echo %count_%" if you do not wish any
progress report output.
@echo off
set count_=.
set target_=...........
:_loop
echo %count_%
choice /cb /t:b,60 /n > nul
set count_=.%count_%
if not "%count_%"=="%target_%" goto _loop
:_end
As so many items, parts of this one owe to the insights of Tom
Lavedas, and parts are totally my own (un)doing.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 65. How can put comments into a batch file?
===========================================
There are three major options, rem, ::, and %%. Rem is the best
known, %% the least. The advantage with %% is that in can be used as
a trailing comment on a working batch line. The example below
illustrates. Furthermore, a rem can be used to create an empty file.
@echo off %Comment: Turn off the echo%
rem > empty.tmp %Comment: Create on empty file%
dir empty.tmp
::
:: Comment: Test if the drive can be written to
if exist empty.tmp echo drive is writable
rem
rem Comment: Delete the empty test file
if exist empty.tmp del empty.tmp
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 66. How can I echo just the word "off" in a batch file?
=======================================================
One can't use "echo off" since that is a command for turning off the
echo. The seldom, if ever, needed curiosity, taken from "MicroSoft's
Undocumented Features, Volume 1 Number 7" is this
@echo off
echo.off
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 67. How can I extract the first two characters of a file name?
==============================================================
The batch below shows how to do the task. It assumes that you have
QBASIC available. QBASIC.EXE comes with MS-DOS, at least with
version 6.22. If you have Windows95 first get it and the related
.HLP files from the system's CD-ROM. I do not use Windows95 myself,
but I believe that these files are located at \OTHER\OLDMSDOS.
The ideas utilized below can easily be applied to other string
manipulation tasks as well.
@echo off
::
:: If no parameter is given to the batch, show its proper usage
if "%1"=="" goto _help
::
:: Prepare a QBASIC program to extract the first two characters
:: Handle different file name types like NAME.DAT NAME and .DAT
echo LET a$="%1" > tmp$$$.bas
echo LET p = INSTR(1, a$, ".") - 1 >> tmp$$$.bas
echo IF p = 0 THEN LET a$ = "" >> tmp$$$.bas
echo IF NOT (p=-1) AND NOT (p=0) THEN LET a$ = MID$(a$, 1, p) >> tmp$$$.bas
echo LET a$ = MID$(a$, 1, 2) >> tmp$$$.bas
echo OPEN "tmp###.bat" FOR OUTPUT AS #1 >> tmp$$$.bas
echo PRINT #1, "@echo off" >> tmp$$$.bas
echo PRINT #1, "set first2_=" + a$ >> tmp$$$.bas
echo SYSTEM >> tmp$$$.bas
qbasic /run tmp$$$.bas
::
:: Call the batch created by the QBASIC program
call tmp###.bat
::
:: Demonstrate that the result is in the first2_ environment variable
echo The first two characters of the file name %1 are %first2_%
goto _end
::
:_help
echo Usage %0 [NameToBeTruncated]
::
:: Cleanup
:_end
if exist tmp$$$.bas del tmp$$$.bas
if exist tmp###.bat del tmp###.bat
set first2_=
The above is not the only alternative. One can do this particular
task also without QBASIC with the trick also used in explaining
"getting the file name extension". Ralf Buschmann kindly posted the
following, instructive solution. Ralf's posting is somewhat edited
below. It is slightly less general than the QBASIC solution, since
it does not test where the basename ends.
"Here is a different approach, that does not need QBASIC. It uses
an undocumented feature of the FOR command in this versions of DOS.
The command
for %%d in (/filename.ext) do echo %%d
will result in
echo f
echo ilename.ext
The "/" character causes to "cut off" the first char of the string
in MS-DOS 6.22 (but not in MS-DOS 7).
@echo off
if "%1"=="" goto error
if "%2"=="" goto error
set chars=
if exist count.$$$ del count.$$$ >nul
set string=%1
::
:loop
for %%d in (/%string%) do set word=%%d
for %%d in (/%string%) do if %%d%word%==%string% set chars=%chars%%%d
set string=%word%
echo x>>count.$$$
find /c "x" count.$$$|find "%2" >nul
if errorlevel 1 goto loop
::
set word=
set string=
del count.$$$
echo The first %2 characters of "%1" are "%chars%".
goto out
::
:error
echo Usage: GETCHARS [String] [NumberOfChars]
::
:out
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 68. How can I compare two numbers with batch commands?
======================================================
There are a number of batch tasks which are readily possible by
using QBASIC. QBASIC.EXE comes with MS-DOS, at least with version
6.22. If you have Windows95 first get it and the related .HLP files
from the system's CD-ROM. I do not use Windows95 myself, but I
believe that these files are located at \OTHER\OLDMSDOS. Using
QBASIC as an aid in batch files opens a Pandora's box of
possibilities.
One hitch in using QBASIC in batch files is that ">" and "<" are
not available, since their nature as batch redirection symbols is
overrides their role as comparison operators. The batch for the
comparison of two numbers given below demonstrates one case of
needing to circumvent the redirection / comparison symbol dilemma.
The result of comparing the two numbers is coded as follows. If
the first is smaller, equal, greater than the second the environment
variable gt_ is returned as -1, 0, and 1, respectively. (As some
programmers will recognize, this resembles the early FORTRAN
convention.)
@echo off
if "%2"=="" goto _help
::
echo IF INSTR(STR$(%1 - %2), "-") = 0 THEN > tmp$$$.bas
echo LET gt$ = "1" >> tmp$$$.bas
echo ELSE >> tmp$$$.bas
echo LET gt$ = "-1" >> tmp$$$.bas
echo ENDIF >> tmp$$$.bas
echo IF %1 = %2 THEN gt$ = "0" >> tmp$$$.bas
echo OPEN "tmp###.bat" FOR OUTPUT AS #1 >> tmp$$$.bas
echo PRINT #1, "@echo off" >> tmp$$$.bas
echo PRINT #1, "set gt_=" + gt$ >> tmp$$$.bas
echo SYSTEM >> tmp$$$.bas
qbasic /run tmp$$$.bas
call tmp###.bat
echo %gt_%
goto _end
::
:_help
echo Usage %0 [FirstNumberToBeCompared] [SecondNumberToBeCompared]
::
:_end
if exist tmp$$$.bas del tmp$$$.bas
if exist tmp###.bat del tmp###.bat
set gt_=
Operations which do not initially require a ">" are more
straightforward. Below, as an example, is a further example batch to
do simple arithmetic operations utilizing QBASIC.
@echo off
::
:: Check that the syntax is right
if "%3"=="" goto _help
set ok_=false
if "%2"=="+" set ok_=true
if "%2"=="-" set ok_=true
if "%2"=="*" set ok_=true
if "%2"=="/" set ok_=true
if "%2"=="^" set ok_=true
if "%2"=="\" set ok_=true
if "%2"=="mod" set ok_=true
if not "%ok_%"=="true" goto _error
::
:: Error message to be used should the QBASIC program fail
echo @echo Illegal operation! The QBASIC program failed.> tmp###.bat
::
:: The calculations using QBASIC
echo ON ERROR GOTO Endit > tmp$$$.bas
echo LET x$ = LTRIM$(STR$ (%1 %2 %3)) >> tmp$$$.bas
echo OPEN "tmp###.bat" FOR OUTPUT AS #1 >> tmp$$$.bas
echo PRINT #1, "@echo off" >> tmp$$$.bas
echo PRINT #1, "set x_=" + x$ >> tmp$$$.bas
echo Endit: >> tmp$$$.bas
echo SYSTEM >> tmp$$$.bas
qbasic /run tmp$$$.bas
call tmp###.bat
::
:: Show the result
if not "%x_%"=="" echo %x_%
goto _out
::
:: Errors and help
:_error
echo Unknown arithmetic operation %2
:_help
echo Usage: %0 FirstOperand ArithmeticOperation SecondOperand
::
:: Cleaning
:_out
if exist tmp$$$.bas del tmp$$$.bas
if exist tmp###.bat del tmp###.bat
set ok_=
set x_=
Here is another, very similar solution for the comparison. It uses
the SGN function.
@echo off
::
if "%2"=="" goto _help
::
> tmp$$$.bas echo LET a = %1
>> tmp$$$.bas echo LET b = %2
>> tmp$$$.bas echo OPEN "tmp###.bat" FOR OUTPUT AS #1
>> tmp$$$.bas echo PRINT #1, "@echo off"
>> tmp$$$.bas echo IF SGN(a - b) = 1 THEN
>> tmp$$$.bas echo PRINT #1, "set sgn=1"
>> tmp$$$.bas echo ELSEIF SGN(a - b) = -1 THEN
>> tmp$$$.bas echo PRINT #1, "set sgn=-1"
>> tmp$$$.bas echo ELSE
>> tmp$$$.bas echo PRINT #1, "set sgn=0"
>> tmp$$$.bas echo END IF
>> tmp$$$.bas echo CLOSE #1
>> tmp$$$.bas echo SYSTEM
::
qbasic /run tmp$$$.bas
call tmp###.bat
::
if "%sgn%"=="1" echo The first parameter is bigger than the second
if "%sgn%"=="-1" echo The first parameter is smaller than the second
if "%sgn%"=="0" echo The parameters are equal
::
del tmp$$$.bas
del tmp###.bat
goto _end
::
:_help
echo Usage: %0 FirstNumber SecondNumber
:_end
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 69. All these solutions are for wimps. Why not rather use 4DOS?
===============================================================
4DOS is a fine alternative command interpreter that can be used to
replace MS-DOS COMMAND.COM. There are many tasks that can be
performed simply and effectively with it. For example, arithmetic
calculations considered earlier in this FAQ could be easily done
with EVAL instead of using the BASIC solutions of the vanilla
MS-DOS. However, using 4DOS also poses some problems.
1) You have to decide whether the extra features are worth the
hassle of changing the command interpreter.
2) You have to weigh the advantages against the inconvenience of
the incompatibilities. Not only of batches, but some programs
will cease working properly if you change your command
interpreter.
There always are better, or just other solutions, which the users of
an alternative system are eager to press on others. This is why one
often can see on the Usenet operating system advocacy postings which
are almost religious in their fervor.
Whatever the pros and cons of 4DOS vs. COMMAND.COM, this package
has been written for vanilla MS-DOS. It does not utilize any 4DOS
additional features.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 70. How can I give more than the nine parameters to a batch?
============================================================
If you need to preserve the parameters for later usage in the batch,
the method is the one below. SHIFT is a batch command that shifts
(what else) left the positions of the replaceable parameters.
@echo off
set _1=%1
shift
set _2=%1
shift
set _3=%1
shift
set _4=%1
shift
set _5=%1
shift
set _6=%1
shift
set _7=%1
shift
set _8=%1
shift
set _9=%1
shift
set _10=%1
:: Test
echo %_1% %_2% %_3% %_4% %_5% %_6% %_7% %_8% %_9% %_10%
Beware, however, lest the command line call exceed the maximum
length of an MS-DOS line.
If you just need the paramters once, you can use a loop
@echo off
if "%1%"=="" goto _end
:_loop
echo %1
shift
if not "%1"=="" goto _loop
:_end
echo Finished
Or, alternatively
@echo off
:_loop
if "%1"=="" goto _out
echo %1
shift
goto _loop
:_out
echo Finished
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 71. How can I update copy files from one directory to another?
==============================================================
Copying more recent files is a task which is best done with a third
party utility like
112492 Sep 7 1993 ftp://garbo.uwasa.fi/pc/filecopy/pcopy93.zip
pcopy93.zip Norm Patriquin's fabulous copy program
18016 Sep 29 1992 ftp://garbo.uwasa.fi/pc/pcmagutl/dirmat31.zip
dirmat31.zip Dirmatch update for comparing & manipulating two dirs
It is, however, possible to use a batch only solution even if it is
not as crisp.
@echo off
::
:: Decide where to go
if "%3"=="recurse" goto _subru
if "%2"=="" goto _usage
if not exist %1 goto _nofiles
::
:: Do it one file at a time
for %%f in (%1) do call %0 %%f %2 recurse
goto _end
::
:_subru
dir %1 | find /v " Volume " | find /v " Directory " | find /v " bytes"
echo %1
replace /u /p %1 %2
goto :_end
::
:_nofiles
echo File %1 not found
goto :_end
::
:_usage
echo Usage: %0 [drive1:][path1]filename [drive2:][path2]
::
:_end
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 72. How can I best clear all the files from my TEMP directory?
==============================================================
First a warning. Be very careful with this solution, since DELTREE
is a very powerful command.
@echo off
::
:: Require running under vanilla MS-DOS
set | find "windir=" > nul
if errorlevel==1 goto _1
if errorlevel==0 goto _0
:_0
echo Do not run this batch under Windows
goto _out
:_1
::
:: Customize the next line. Be vary careful!
set tempdir=c:\temp
if "%tempdir%"=="" goto _nospace
::
:: Check if there is anything to delete
if not exist %tempdir%\*.* goto _nofiles
deltree /y %tempdir%\
goto _out
::
:_nofiles
echo No files in, or no %tempdir%
goto _out
::
:_nospace
echo Warning! You are out of environment space
::
:_out
set tempdir=
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 73. How can I check the number of parameters given to a batch?
==============================================================
A pedestrian solution to this question is
@echo off
if not "%9"=="" echo at least 9 replaceable parameters
if "%9"=="" if not "%8"=="" echo 8 replaceable parameters
if "%8"=="" if not "%7"=="" echo 7 replaceable parameters
if "%7"=="" if not "%6"=="" echo 6 replaceable parameters
if "%6"=="" if not "%5"=="" echo 5 replaceable parameters
if "%5"=="" if not "%4"=="" echo 4 replaceable parameters
if "%4"=="" if not "%3"=="" echo 3 replaceable parameters
if "%3"=="" if not "%2"=="" echo 2 replaceable parameters
if "%2"=="" if not "%1"=="" echo 1 replaceable parameters
if "%1"=="" echo no replaceable parameters
This is not, however, a very essential batch task since e.g. "shift"
can be used to access one parameter at a time until the parameters
are exhausted.
Another solution is a batch that gives the output as a number of
characters (.)
@echo off
set count_=
:_loop
if "%1"=="" goto _endloop
shift
set count_=%count_%.
goto _loop
:_endloop
if not "%count_%"=="" echo %count_%
if "%count_%"=="" echo No parameters
This method has the disadvantage of losing the parameters because of
the shift.
A rather neat solution was posted by Walter Zackery:
@echo off
>>{c}.bat for %%f in (1 2 3 4 5 6 7 8 9) do echo if not "%%%%f"=="" set c_=%%f
call {c} %1 %2 %3 %4 %5 %6 %7 %8 %9
if exist {c}.bat del {c}.bat
echo %c_% parameters entered at the command line.
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 74. How can I locate and e.g. delete all *.TMP files on a drive?
================================================================
The locating part is not difficult with a batch, but also performing
an operation on the files found is. Therefore, I'll recommend a
third party solution for the latter part. As for the first part, you
can use the ATTRIB command as follows
@echo off
attrib +a c:\*.tmp /s > nul
attrib c:\*.tmp /s > go.bat
Then you'll have a list like
A C:\AN\ARCHIVE.TMP
A C:\AN\NOTES.TMP
A C:\AN2\NOTES2.TMP
The next question is how to manipulate that list of files. One
non-batch solution is to use an editor to substitute the " A" (or
whatever) with an MS-DOS command, like DEL.
A different, stand-alone solution is to use a specified
third-party program for the purpose. The best choices are the very
useful and flexible TARGET
73962 Jul 21 1992 ftp://garbo.uwasa.fi/pc/filefind/target15.zip
target15.zip The McAfee File Locator and Manipulator (good)
and the more narrow-scope
17653 Dec 13 1987 ftp://garbo.uwasa.fi/pc/pcmagvol/vol4n24.zip
vol4n24.zip Contains SWEEP and WAITASEC
Also see the later item "How to search all the *.txt files on a
drive for a word?"
--------------------------------------------------------------------
Introduction
Index
Articles
Download the text file version
with samples and utilities 75. How can I rename all files sequentially in a directory?
===========================================================
Q: How can I rename all files in a directory into a sequential
numerical order? E.g. 001.txt, 002.txt, 003.bat, 004.ico.
A: This is an interesting task. The solution I have used for a
similar task involves an editor, which is effective but not very
neat batch programming. For a batch only solution one alternative is
to utilize QBASIC which is part of MS-DOS. The solution below can
easily be streamlined to do the renaming automatically, but I have
erred on the side of caution. Yes, don't damage your file structure
with haphazard experimenting. First make sure that you understand
what the batch does.
Also note that while this batch is for all the files in a
directory, it is very easy to change it to cover only one time of
files. Just change argument in the second line of the batch.
@echo off
dir /b /l *.* > dirlst$$.tmp
echo OPEN "dirlst$$.tmp" FOR INPUT AS #1 > tmp$$$.bas
echo OPEN "sequence.bat" FOR OUTPUT AS #2 >> tmp$$$.bas
echo PRINT #2, "@echo off" >> tmp$$$.bas
echo PRINT #2, "rem SEQUENCE.BAT by Prof. Timo Salmi" >> tmp$$$.bas
echo PRINT #2, "" >> tmp$$$.bas
echo LET i = 0 >> tmp$$$.bas
echo DO >> tmp$$$.bas
echo LINE INPUT #1, a$ >> tmp$$$.bas
echo IF NOT INSTR(a$, ".") = 0 THEN >> tmp$$$.bas
echo IF NOT a$ = "dirlst$$.tmp" THEN >> tmp$$$.bas
echo IF NOT a$ = "sequence.bat" THEN >> tmp$$$.bas
echo LET i = i + 1 >> tmp$$$.bas
echo LET i$ = LTRIM$(STR$(i)) >> tmp$$$.bas
echo LET z$ = STRING$(3 - LEN(i$), ASC("0")) >> tmp$$$.bas
echo LET e$ = MID$(a$, INSTR(a$, ".")) >> tmp$$$.bas
echo PRINT #2, "copy /-y "; a$; " "; z$; i$ + e$ >> tmp$$$.bas
echo END IF >> tmp$$$.bas
echo END IF >> tmp$$$.bas
echo END IF >&g | |