About site: Software/Operating Systems/x86/DOS/Programming/Languages/Batch - Timo Salmi's Assorted Batch Tricks
Return to Computers also Computers
  About site: http://www.macalester.edu/~fines/batch_tricks.htm

Title: Software/Operating Systems/x86/DOS/Programming/Languages/Batch - Timo Salmi's Assorted Batch Tricks Practical and educational examples including a few obscure techniques.
WebBuilder101_com Provides valuable free information and tutorials about web building, and Internet surfing.

IMS_Glossary_of_Terms_and_Acronyms Common technical terminology used to describe concepts within IMS/TM and IMS/DB. From IBM.

KnowlegeBridge_by_Websoft_Systems A robust Learning Content Management Systems architecture allowing distributed teams of non-technical editors to manage e-learning content seamlessly.

Sydney_Ruby_Users_Group RubyGarden Wiki Page for Sydney's RUG

Philex Tool for managing website content or Intranet/Extranet environments. Uses PHP, Javascript and MySQL. Modular code, multi-language support. [Open Source]

SyncSort_for_Windows Minimizes sorting time for large volumes of data and significantly improves the performance of enterprise applications.


  Alexa statistic for http://www.macalester.edu/~fines/batch_tricks.htm





Get your Google PageRank






Please visit: http://www.macalester.edu/~fines/batch_tricks.htm


  Related sites for http://www.macalester.edu/~fines/batch_tricks.htm
    3D_Chat_Programs_Review A review of 3D chat programs, comparing prices, number of people in each, avatar types and world costs.
    Flightsim Simulating the passenger side of flying.
    The_Sources_Store_for_Modula-2_and_Oberon-2_Programming_Languages The purpose of this site is free propagation of any source code and documents related to Modula-2 and Oberon-2.
    RFC_3295 Definitions of Managed Objects for the General Switch Management Protocol (GSMP). H. Sjostrand, J. Buerkle, B. Srinivasan. June 2002.
    Modern_Minds,_Inc Telnet application.
    Birds-Eye_Network_Services Provides self-service network monitoring to customers who are connected to the Internet.
    Digiscribe Document scanning, indexing, web-based retrieval, and litigation support. Pick-up and delivery service, off-site, secure data storage. Voice transcription and data entry service. Located in Elmsford,
    Better-Whois_com Queries all registrars and allows users to receive detailed whois reports via e-mail.
    Tivoli_Glossary Terms used by IBM subsidiary Tivoli. Glossary can be used on-line or downloaded in Adobe Acrobat .pdf file format.
    UnrealDownload A free, open source download manager written in C#.
    Autothemes_com_ Commercial and custom development of autothemes compatible with the latest version of Autothemes software and available for PHP-Nuke, PostNuke, CPG-Nuke, MD-Pro, Envolution and OScommerce.
    CONTACT_Software_GmbH CONTACT Software provides solutions for CAD data management, product data management (PDM) and product lifecycle management (PLM). In addition CONTACT offers consulting and training services.
    RFC_3062 LDAP Password Modify Extended Operation. K. Zeilenga. February 2001.
    Code-VB Visual Basic and VBA coding tools including declaration, class, property, procedure, flow, fragment builders, control builder, code snippets library. All tools are integrated with each other. Includes
    Pagesbydave_Javascript_Library Cut and paste javascripts collection.
    TBC_Creative Offers design, maintenance, and flash services.
    McIntosh_Web_Designs Web design for small businesses. Javascript, domain registration, and animations available. Located in Woodlands, Texas, United States.
    FB_Pouch Excellent searchable FB site contains help and code snippets for all sorts of stuff.
    Quote_Colors An extension for the Mozilla Mail client that adds a user interface for configuring text and background colors for different quote levels when displaying messages.
    RocketTheme Joomla! templates club that offers professional quality designs for its members. New Joomla! templates released every month.
This is websites2007.org cache of m/ as retrieved on 2008.08.29 websites2007.org's cache is the snapshot that we took of the page as we crawled the web. The page may have changed since that time.
Timo Salmi's Assorted Batch Tricks

Timo Salmi's Assorted Batch Tricks

Professor 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 

Index

NOTE:       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 

Articles

1. 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