ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» º º º ÞÛÛÝÞÝÞÝÞÝ Û ÞÛÛÝ ÞÝ ÞÛÛÝ ÞÛÛÞÝÞÝ ÞÛÛÝÞÝÞÝÞÝ Û º º Û ÛÞÝÞÝÞÛ Û Û Û ÛÛ ÞÞÝÝ Û ÛÞÝÞÝ Û ÛÞÝÞÝÞÛ Û º º Û ÛÞÝÞÝÞÛÝÛ Û ÛÞÝÞÝ ÞÝ ÞÝ ÞÝÞÝ Û ÛÞÝÞÝÞÛÝÛ º º ÛÛÝÞÝÞÝÞÝÛÛ ÛÛÝÞÝÞÝ ÞÝ ÞÝ ÞÛÛÝ ÛÛÝÞÝÞÝÞÝÛÛ º º ÛÛ ÞÝÞÝÞÝÞÛ Û ÛÞÛÛÝ ÞÝ ÞÝ ÞÝÞÝ ÛÛ ÞÝÞÝÞÝÞÛ º º ÛÞÝÞÝÞÝÞÝ Û Û ÛÞÝÞÝ ÞÝ Û ÛÞÝÞÝ ÛÞÝÞÝÞÝÞÝ Û º º ÞÛ Û ÛÛ ÞÝ Û ÞÛÛÝÞÝÞÝ ÛÛ ÞÛÝÞÝÞÝ ÞÛ Û ÛÛ ÞÝ Û º º º º º ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ The Run Batch Run Book Copyright (c) 1998, Finn Roaas All Right Reserved, World Wide Finn Roaas Postboks 75 - Furuset N-1001 Oslo, Norway froaas@online.no Voice (registrations only) +47 22301372 Fax: +47 22301304 ===================================== RUN BATCH RUN REGISTRATION FORM ===================================== Remit to: Finn Roaas Postboks 75 - Furuset N-1001 Oslo, Norway --------------------------------------------------------------------- | Item | Quantity | Price | Total | |-------------------------------|----------|----------- |------------| | RBatch12 version 1.2 (Nor) | ________ | NOK100.00 | __________ | | | | | | | RBatch14 version 1.4 (Eng) | ________ | $ 15.00 | __________ | | (A Companion Disk included) | | | | | Diskette 3.5 ( ) 5.25 ( ) | ________ | $ 8.00 | __________ | | | | NOK 50.00 | | | Schools (free use 1000 | | | | | students for one year | ________ | NOK1.000,00| __________ | | Subscription | | $ 80.00 | | | Abonnement | ________ | NOK480.00 | __________ | | | | | | | Shipping | ________ | $ 5.00 | __________ | |------------------------------------------------------ |------------| | | | | Total amount enclosed | __________ | ---------------------------------------------------------------------- Payment by: ( ) Check or money order ( ) American Express ( ) Diners Club ( ) MasterCard ( ) Visa ( ) PO # ______________ Card #: ____________________________________ Exp. Date: _________ Signature of card holder: ____________________________________________ Name: ________________________________________________________ Company: ________________________________________________________ Address: ________________________________________________________ ________________________________________________________ ________________________________________________________ Phone: ________________________________________________________ ( ) Check or money order payable to Finn Roaas in U.S. funds enclosed ( ) SWIFT transfer to 6065.56.31588 (Kredittkassen 1067 Oslo, Norway) ( ) SWIFT transfer to 0521 1589665 (Postbanken, Norway) TABLE OF CONTENTS ================= Chapter 1: Save your files - different methods Chapter 2: One day you will regret that you didn't take backup seriously Chapter 3: How to make a choice about how a batch should proceed? Chapter 4: Edit a batch program Chapter 5: Batch pipe problem Chapter 6: Searching for files is often time consuming Chapter 7: Customizing the command dir Chapter 8: How can a batch program answer Y for yes Chapter 9: Batch files can be used with memory and RAM Chapter 10: To remove files accidentally extracted Chapter 11: Choice Chapter 12: How to get the system date Chapter 13: Extracting text strings Chapter 14: Different batch enhancers and using scan codes Chapter 15: Batch files and mail Chapter 16: How to suppress the writing on the screen? Chapter 17: How to have a batch file testing if Windows is running Chapter 18: Invisible cursor Chapter 19: Numbered repeats in batch files Chapter 20: How you can write batch files that will execute certain commands based on the time of day? Chapter 21: Return to directory Chapter 22: Make a log with the time and date Chapter 23: Books, magazines and programs about batch files Chapter 24: Remove file comment Chapter 25: FOR in batch files Chapter 26: Ansi codes in batch file Chapter 27: About errorlevel Chapter 28: Rebooting from a batch file Chapter 29: How to execute a batch file on a certain weekday? Chapter 30: Y/N in batch files Chapter 31: Remap keys Chapter 33: Detecting DblSpace drive Chapter 34: How to add a path to the existing path? Chapter 35: Numlock on Chapter 36: Changing the date during execution Chapter 37: Undocumented commands Chapter 38: Ctrl-c/break Chapter 39: Can't delete directory Chapter 40: Batch file for cd-rom Chapter 41: Get the beep out of CHOICE Chapter 42: How to tell MS DOS not to display any messages? Chapter 43: Recall of previously issued commands for re-entry >>>>@@@@<<<< Chapter 1: Save your files - different methods. =============================================== At the end of this book you will find a presentation of the the author. As you will see I'm also a novelist and a writer of modern norwegian literature. I know how important it is to save my files in a secure and efficient way. The day you have lost important data you will understand the importance of taking good care of all files you produce. When your hard disk is down and one year's work is wasted it is to late to plan how you are going to save your files. Some years ago I lost all chapters in a new book I was writing because of problems with my WC-card. A lot of different thoughts went through my head when I realized what had happened, but fortunately I also remembered that I had copied the files to a floppy. I looked through my diskettes and thank God I found what I was looking for. The floppy made it possible to restore all files to my hard disk. As I said, this happened many years ago. Experience has taught me the lessons to take good care of my files. This is our first subject. Let's have a closer look at a batch file I have called SAV1.BAT ======== @ECHO OFF :start IF " %1" ==" " GOTO end ECHO ***%1 will be saved *** IF NOT EXIST A:%1 COPY %1 A: SHIFT GOTO start :end Every day when I had finished writing a manuscript, essays or letters, I needed to save the files to a floppy. The files had different names and I wanted to make a program that was able to copy more than 9 files. I knew that %1 to %9 parameters gave me the opportunity to run nine variables through a batch program, but it was not enough. Then I discovered SHIFT. The command allowed me to use more than nine batch parameters. The SHIFT command moves the parameters one step to the left in a batch file. It moves the remaining parameters down one value, a new %9 is brought in if any exists. In the example above I use the SHIFT command with three parameters. When a SHIFT command is executed, it moves the %3 parameter down to the %2 parameter. The value %2 moves into %1. The original %1 has disappeared. After executing another SHIFT command, the original %3 has become %1, and the original %2 and %3 are both gone. The SHIFT command makes it possible to make a short batch program to execute any number of parameters. The batch file above illustrates this method. SAV1.BAT may be used to backup any number of files. Below you will find a description of how the file works, line by line. The first line turns off the echoing with the command ECHO OFF. The label :START in line 2 marks the start of the command and will be repeated for each parameter. In line 3 the IF command tests if it exists a parameter in the variable %1. The command makes a comparison between %1 and the double quotation marks enclosing nothing (" "). This is called an empty string. You ask MS DOS to compare the first parameter with nothing or with an empty parameter. If the comparison is true, the GOTO command ends at the label :end. The ECHO command in line 4 shows the name of the file being copied. The IF command in line 5 lets your batch file test if the files you save exists on the diskette in A. If it not exists the COPY command copies the file from the active drive and directory to A:. In line 6 the SHIFT command moves parameters one step to the left. The GOTO command in line 7 returns MS DOS to :START. The label :end in line 8 marks the end of the of the batch file. You run SAV1.BAT with the following command line: C:\> SAV1.BAT autoexec.bat config.sys command.com The batch file ends when %1 is equal to " " - or in another words - when it is no files left to copy. But the batch file won't stop. It displays this message: Syntax error *** will be saved *** A: File not found 0 File(s) copied. The quickest way to end the program is to press CONTROL - C. The command has the following syntax: SAV1 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 I usually name my manuscripts, essays and letters with, short abbreviations like CHAP1 etc. The end of the batch program above is far from impressing. But as long as you use the correct syntax and the file exists the job is done. Immediately you write a filename that does not exit or the file does not exist, you'll get an error message. When the job is done, the SHIFT command runs in loop. I finish with Control-C. Not very elegant, but SAV1.BAT gives you an idea how the SHIFT command works. SAVE.BAT ======== @ECHO OFF CLS REM PRESS THE TAB WHEN ECHO IS DONE ECHO *** SAVE *** ECHO. ECHO Have you inserted the floppy in drive A: REM The warning will not be displayed if already saved IF NOT EXIST A:%1 GOTO ready ECHO REM CTRL-G creates i bip ECHO a:%1 exists. Press CTRL-BREAK to terminate, or... PAUSE :ready COPY %1 a:%1 IF EXIST A:%1 erase %1 ECHO ECHO %1 has been saved to the diskette! I have always been looking for good methods to protect and save my work, but I have also been looking for ways to control the performance. In long periods I have made use of the batch program above. Only when a certain condition exists or come true, for example a certain file exists, the command will be issued. I noticed immediately that the method improved my batch files. The method may be used in many different situations, what you will find in this book. The IF command is used when you want a batch command to be carried out only after certain conditions have been met. For example, the following command starts Qedit when Q is used as a parameter: IF "%1"=="Q" D:\QE3\Q The command use three parameters: IF (NOT) The parameter NOT specifies that MS DOS should carry out the command only if the conditionis false. In the parameter it is the condition that must be met. There are two ways to use : EXIST tests wether a specified file exists or not. Sometimes the system needs the path and directories written. If the exists, the condition is met. == compare two strings. These values can be strings or batch variables such as %1. If the strings are identical, the condition is met. Notice that two equal signs are required. is any MS DOS command. The command CLS in line 2 makes batch file starts with cleared screen, and the user sees only the message. The command REM in line 3 reminds us of that the space in line 4 is produced by pushing the tab key three times. The headline * * * SAVE * * * in line 4 shows up, and is displayed in the center, because we have pressed three times on the tab key. The command ECHO in line 5 displays empty line just below the headline. is the ASCII code for empty character. To produce ANSI characters that are not on your keyboard, you have to use the following method: Hold down Alt and type the number that corresponds to the character you want NumLock must be on. Then release Alt. The command REM in line 8 makes a comment on the command GOTO in line 9. There is another command ECHO in line 10. It has a dot and displays en empty line to make the warning more visible. The command REM in line 11 comments the sound in line 12 and it's used together with ECHO. Hold down CTRL and type G The command ECHO in line writes a message du the screen: The file has been saved to the diskette. COPY ALL FILES ============== Neither COPY *.* nor XCOPY *.* copy all files if you want to copy to more than one diskette. But there are easy methods to get COPY *.* to do what you want the command to do, namely copy all and don't leave out files because the diskette is full. Below I will take a detailed look at two little used methods to search for bugs in batch files. I will also look at a smart way how you can run "for in .. do" loops without display a lot garbage! The COPY *.* A: means: Copy all files from your hard disk to drive A:. Did I type all? Yea, but that's exactly what it doesn't do. Suddenly the diskette in drive A: is full. The floppy in drive A: takes only 720 Kbyte, but you need maybe to copy 900 Kbyte. If you want to backup the rest of your files, you will really get a difficult job to find the files you're missing. There are at least four ways to use to copy all files. The first I will discuss is the most time consuming one. Copy *.* to A:. Write the name of the last file listed on a sheet of paper. This file was not copied to A:. Type DIR/p and notice all files that are listed below the file you have written on the sheet of paper. These are the files that you still haven't copied. Why is it so? Because the command DIR and COPY treat the files in the same way. You have to copy the listed files manually. It's a boring job. But the command XCOPY does copying files simple and easy. Type XCOPY *.* A:/p. Now you have to answer yes/no for each file you will copy. At the beginning of the list you just answer N for NO. When you reach the file you have written on your sheet of paper, you start answering Y for Yes. It's easy to make a list of all the files you haven't copied. Type the three lines below: ECHO OFF FOR %a IN (*.*) DO IF NOT EXIST A:%a ECHO %a ECHO ON þ The first line turns off the PROMPT. þ The third line displays the PROMPT. þ Unless you want your screen filled up with unnecessary information it's recommended use ECHO OFF and ON. The second line demonstrates how you can make a "for in .. do-loop" in MS DOS without writing it into a batch file. After typing the commands above a list of files is displayed. Stop the scrolling by pressing Ctrl-S. (Don't make mistakes. Don't type %a on one side and %A on the other side of the parenthesis. Don't make mistake number two: Use %%a if you write a batch program. Don't make mistake number three: MS DOS has problems copying files with 0-bytes. May be one of your files is a 0-byte file. Sometimes the prompt disappears. This happens for example when you terminate a batch file or run another batch file using CALL. Or may be your batch file doesn't run properly. Instead of reboot, type ECHO ON. Sometimes it occurs that MS DOS can't remember wether echo is on or off. In creating batch programs you often find yourself testing the files over and over again. A simple "debug-trick" is to leave out @ECHO ON in the first line when you run the file. You save time. You don't need to edit and save all the time. An other method is to place a variable for ECHO OFF. If your first line is @%test% ECHO OFF you can turn ECHO on and off with the command SET! Type: SET TEST=REM and run the batch file with ECHO on. Type SET TEST= run the batch file with ECHO off. TOA.BAT provides an easy way to create an advanced batch file which types a list containing the names of all files in the directory, make a copy from the list and at last displays it. Look at TOA.BAT below, it's a nice piece of work. The program use the command XCOPY to copy possible 0 byte files, and because XCOPY reports when the diskette is full. Run TOA.BAT without any arguments at the prompt. MS DOS moves to the label :START and deletes the old file catalog called, LISTE.BAT. TOA.BAT uses a temporary batch file to run itself repeatedly. The program copy all files of a directory to several floppy diskettes. TOA.BAT ======= @ECHO OFF IF %1X==X GOTO START IF %1==CATALOG.BAT GOTO END COPY %1 A:>NUL IF EXIST A:%1 GOTO END REM Don*t stop because of 0 byte files: XCOPY %1 A: IF EXIST A:%1 GOTO END ECHO Change diskette in A: - Insufficient disk space for %1 PAUSE %0 %1 :START IF EXIST CATALOG.BAT DEL CATALOG.BAT FOR %%a IN (*.*) DO ECHO CALL %0 %%a >>CATALOG.BAT CALL CATALOG DEL CATALOG.BAT :END Normally when you try to delete files that do not exist, you get the error message "File not found". This message is confusing and many of you will jump on the keyboard and press CTRL-C. What's going on! The program is supposed to copy files and can't find the file! To avoid error messages we will first check it out TOA.BAT IF CATALOG.BAT exists by executing the command IF EXIST i line 13. If you already got a file called CATALOG.BAT you need to change the name, and find another unique name to your catalog. The catalog reporting all the files in the directory is created in a FOR-IN-DO-LOOP. We create the list with double redirection operators >> in line 14. A new will be added for each new filename. Preceding each filename you find the command CALL TOA. If you are using a MS DOS version earlier than 3.3 you must use COMMAND /c to run a batch file from within another. You can't use CALL. When you run CATALOG.BAT MS DOS executes the CALL CATALOG in line 15. The format of the command CALL is as follows: CALL parameters But what exactly does CALL TOA? It starts TOA.BAT program and accepts file name as a parameter. The parameter is a file name in the directory. TOA.BAT try to copy files A:. If TOA.BAT can't make it, the program asks for a new diskette i A: and you must try again. Notice that TOA.BAT in the third line 3 pass CATALOG.BAT. We don't need to copy the temporary and specific report. þ TOA.BAT creates and starts CATALOG.BAT. CATALOG.BAT starts TOA.BAT successive before each file name. When the last file has been copied, we are back to the starting point. The temporary file CATALOG.BAT is erased, the batch file ends and returns to MS DOS. þ I use %0 when the program is asked to call it self. If you rename the file TOA.BAT to CHINABOX.BAT, you can type CATALOG.BAT and read CALL CHINABOX FILE NAME in CATALOG.BAT. þ The at sign @ and the command CALL works only in MS DOS versions 3.3 and later. The command XCOPY was new in MS DOS 3.2. If you don't use XCOPY you have to delete all files with 0 byte before you execute the batch file. Method number three is the simplest. With number one you had to remember files that you wanted to copy. TOA.BAT created a file called CATALOG.BAT that kept a record of all the files in the directory. In this method we will use the archive attribute as an invisible label attached to each file. By turning off the archive attribute with the command ATTRIB +A *.*. XCOPY/m copy only those files where the attribute is not set. Think of the attribute as a label where it's written: "must be copied". All the files have now got such a memo. Then I start XCOPY: XCOPY *.* A:/m. After a while the diskette is full and XCOPY stops doing the job without asking for a new diskette. That's silly, but the switch /m is handy. The /m switch copies source files that have their archive file attributes set. the /M switch turns off archive file attributes in thefiles specified in source. We insert a new diskette, repeats the command and XCOPY carries on. This is possible because the command XCOPY /m turns off the archive attribute during execution, but only those files that you really copy. Imagine how XCOPY writes on each file: "this is done" and attach the memos to the copied files. As you can see, it's easy to continue. Repeat the command (press F3) when you have changed the diskette. XCOPY will continue coping files. When the batch is done turn on the archive attribute, for the cause of safety. The next batch file, CPTOA.BAT, contains these commands: The program draws the maximum benefit from XCOPY'S little known and often unused ability to provide exit-status values that you can test using ERRORLEVEL codes. (See ERRORLEVEL codes in chapter 27 in this book.) CPTOA.BAT ========= @ECHO OFF IF %1.==. GOTO END IF %a%X==X ATTRIB +A *.* SET A=some :AGAIN XCOPY *.* %1 /m/w IF ERRORLEVEL 4 GOTO AGAIN IF ERRORLEVEL 2 GOTO END ATTRIB +A *.* SET A= :END IF %1.==. ECHO %0 A: or ? To start the program type drive A: or B: on the PROMPT command line. This is possible because Initialization error occurred. There is not enough disk space, and produces and errorlevel 4. XCOPY has stopped to copy files, but there are still more left. That's why the MS DOS batch file is asked to go to :AGAIN in line 5. XCOPY starts. XCOPY/m/w means that the program is waiting for an keyboard input so you can change the diskette. This is how we avoid an extra command PAUSE. If you want to terminate you can easily use Ctrl-C which provides ERRORLEVEL 2. May be something is wrong or you have no formatted diskettes left. But I assume that you plan to carry on, so no steps are taken to restore the archive attributes. This is the reason why I create a new system variable in the line SET A=something. If you stop the execution, the system variable A will still be there. When MS DOS encounters %A% in line number 2 ATTRIB is not executed. In other words: CPTOA.BAT continue where it stopped. The line SET A= at the end removes A so you can run the batch file in other directories. CPTOA.BAT must be in PATH. If you wonder what the use of the @ symbol in a batch file is for, this is the explanation: As far as I can see, the only thing the "@"-symbol does, when used in batch files, is the same as an "echo off". When you have a one-liner batch file which just says @ver the MS-DOS version will be displayed without the "ver" command also echoed. If youïve come this far, you should have a pretty good understanding of how important it is to save your files and know some methods on how to do it. I haven't discussed everything there is to know about saving files, oh course, but you have come familiar with some powerful batch files and terms you're likely to run into in your day-to-day dealings with your computer and MS DOS. If you should decide to make use and test out the batch files in this chapter, you can get a companion disk sent to you by e-mail or, if you haven't an email address, on a diskette, all you have to do is to register yourself as a supporter of this book. At last a batch program that bump the file one at a time from at ramdisk to a directory called ARCHIVE. As usually the file starts with turning the echo off. The next line also has an ECHO followed by a dot which normally produce an empty line. The third line consists of an IF statement. If the strings are the same the statement will not be handled and the processing moves on to no_file. At no_file you are presented with a help text telling you the meaning of the file and how you should use it. The next line continues the processing and is caused by the line above. MS DOS wil write a message on screen pointing out the problem for you, namely File not found and terminate the batch program. The line is an IF NOT EXIST statement. Then the new directory will be created, MD Archive. A new tests finds out if the directory exists, and if it does moves on to dir_exists. A new message is written to the screen to inform the user that it's not possible to create a new directory by the same name. It is also convenient to test whether the directory is empty or not? Then the command COPY is used to bump the file from for example your ram-disk to C:\ARCHIVE. The /v switch verifies if the new file is written correctly and the execution will be slower, though everything is relative. The command STOP.COM is similar to PAUSE, but STOP allows you to write your own text that moves from the right side of the screen to left. STOP.COM is one of the many DEBUG programs on the RUN BATCH RUN Comapanion disk, both the script and the com file. TO_ARCH.BAT =========== ECHO OFF ECHO. IF "%1"=="" GOTO no_file IF NOT EXIST %1 GOTO file_not_found MD C:\ARCHIVE IF NOT EXIST C:\ARCHIVE\nul GOTO dir_exists IF EXIST C:\ARCHIVE\*.* GOTO dir_not_empty COPY /v %1 C:\ARCHIVE\%1 ECHO %1 copied to C:\ARCHIVE\%1 STOP IF EXIST %1 GOTO in_tree COPY /v C:\ARCHIVE\%1 %1 ECHO C:\ARCHIVE\%1 copied to %1 GOTO trash :in_tree ECHO %1 already exists! ECHO Apply break to exit without copying ECHO (IF you break, you must then manually remove the ARCHIVE directory and its files) STOP COPY /v C:\ARCHIVE\%1 %1 ECHO C:\ARCHIVE\%1 copied to %1 GOTO trash :no_file ECHO Usage TO_ARCH.BAT is to bump a File Name Without Path ECHO. ECHO This batch is intended for bumping one file at a time from your ECHO ramdisk to the directory you use for saving files you work with on a ECHO ramdisk. ECHO Wildcards are allowed, but not recommended. Do not make use of path ECHO together with your filenames. GOTO _out :file_not_found ECHO File %1 not found GOTO _out :dir_exists ECHO It's not possible to create directory C:\ARCHIVE GOTO _out :dir_not_empty ECHO C:\ARCHIVE is not empty GOTO _out :trash IF not "%1" == "*.*" GOTO trash2 IF NOT EXIST C:\ARCHIVE\%1 GOTO clean_up ECHO y|del C:\ARCHIVE\%1 > nul GOTO clean_up :trash2 IF EXIST C:\ARCHIVE\%1 del C:\ARCHIVE\%1 :clean_up RD C:\ARCHIVE :_out ECHO on Chapter 2: One day you will regret that you didn't take backup seriously ======================================================================== You want to backup the files and directories from your computer's hard disk to high density floppies. This is something you have never done before, so yiu are nervous about trying. This is good. Your nervousness makes you cautious enough to ask questions (and intelligent ones, at that). Before I reveal my system I would like to add a few comments of my own. First, your backup will depend on what DOS version you are running or the size of the HD you wish to back up. Not terribly important, but worth some consideration. XCOPY isn't a very good choice when you are speaking of backing up any HD. But, it is an excellent tool for this purpose when speaking of a few files/directories. Especially when restoration may be expected on a different DOS machine that may not contain any software tools other than basic DOS. DOS's original BACKUP/RESTORE combo is a notoriously cranky old beast. I have a lot of experience with it, personally and professionally, and would not recomend it. Actually, I don't think any knowledgable person recommends it. It is workable and reliable, just difficult and inefficient. MS-BACKUP that comes with DOS 6.x is good for both novice and advanced users (although there are much better third party routines available). You won't go wrong by using this. There is a third method that is also quite popular. Using a file compression program such as PKZip or LHA. As an example, PKZip 2.04g will use 65% of the number of disks that MS-BACKUP requires (eg: pk=23 when ms=35), spans multiple disks with ease, it will do a backup in about 50% of the time, and it is very portable. As a practical consideration, copy PKUnzip.exe to the first disk of your backup set (making the set self-contained). You can quickly restore the backup on any machine that runs almost any version of DOS. Lastly. If your HD is a large one, you may want to consider not using disks at all. Investing in a tape drive may be the cheaper alternative. Here is what I usually council my clients. Do general full backups to tape and also backup critical data files to disk as an additional safeguard. Time and monetary costs are minimized, while retaining high reliability. You might think about trying PKzip to compress all this stuff on to the floppy. You get at least 1.5 to 1. and sometimes 2 to 1. You can download a testdrive PK204g.zip from most BBSs. As I understand it, the BACKUP command will fill up each floppy "to the brim", and will split files between diskettes, if PK will do this too. You would appreciate knowing: What is the difference between the quality of the results from the BACKUP and XCOPY commands? None. Same for PK. Will both commands assign a sequential number to the diskettes (01, 02, 03, etc.) during backing up and also ask for the diskettes in sequential order when restoring the data back to the hard disk? Only Backup and PK (used with the disk spaning switch) will do this. Is there a way to use the BACKUP command so that it will not split files between diskettes? I don't think so. Play with each on a small directory and see which one you like. You can always delete/reformat a floppy and start over with something else. Been using them all for a few years. No fails yet. As you understand it, the BACKUP command will fill up each floppy "to the brim", and will split files between diskettes, if necessary. On the other hand, the XCOPY command will copy only complete files, without splitting a file between two diskettes. For this reason, I am inclined to favor the XCOPY command; but is it OK to have files split between diskettes? Of course it is. If you have a file that's larger than a disk, the XCOPY command can't do the slightest thing with it. Period. Your whole backup would halt at that point and refuse to go any further. The BACKUP command, on the other hand, handles it with the greatest of ease. What is the difference between the quality of the results from the BACKUP and XCOPY commands? No difference in the quality at all. There are a lot of people who think that the BACKUP/RESTORE commands are not reliable, but that is quite false. If you start with floppy disks that are known to be good (in other words they've JUST been formatted WITHOUT the /Q switch and FORMAT did not say that any "bytes in bad sectors" were found), and you know how to use the BACKUP and RESTORE commands, then you have absolutely no problem. But the fact is, most people don't have a clue how to use BACKUP and RESTORE, but since they THINK they do, they blame the problem on the commands when it turns out they can't get their files back. When in actuality, if they simply gave DOS the corrent RESTORE command syntax, they would find all their files returned to them immediately. RESTORE A: C:\*.* /S restores every file on the backup disks to the corresponding directory on the C: drive (creating those directories, if necessary). RESTORE A: C:\WP51\*.* /S restores every file on the backup disks which had originally come from a directory named \WP51, or its subdirectories, to a directory named \WP51 on the C: drive, and its subdirectories (creating the directories if necessary). A lot of people try to restore the \WP51 files from the backup disks to a directory on the hard drive named \WORD, for example. And of course RESTORE says "No files found to restore" because there aren't any \WORD\*.* files on the backup disks. There are only \WP51\*.* files there. RESTORE does not restore files to a directory other than that from which it was backed up, because BACKUP stores files according to their FULL filename, including the directory specification. Another real common mistake people make with BACKUP/RESTORE is they type the directory name instead of the filename they want restored. RESTORE A: C:\WP51 /S tells RESTORE to restore one specific file named WP51 to the root directory of the C: drive. RESTORE doesn't restore directories. It restores files. C:\WP51 doesn't mean the \WP51 directory. C:\WP51\*.* does. Another common one is RESTORE A:*.* C: /S That doesn't mean anything to RESTORE at all. The filename specification belongs on the target side, not the source side. Without the proper syntax, RESTORE will not restore the files that the user THINKS he's telling it to restore. But when the user does tell RESTORE what he really wants done---IN RESTORE'S LANGUAGE, NOT THE USER'S---then RESTORE is just as reliable as can be. No problem whatsoever. Now, there is a difference between the results of BACKUP and XCOPY though, that's not related to quality at all. BACKUP disks can be used only by the RESTORE command. Without RESTORE, those files are inaccessible. And RESTORE can't get to a file on the fifth disk without first going through disks one, two, three, and four. XCOPY, on the other hand, makes disks which contain files in their normal state, which can be accessed by any DOS command at all. So you can use DIR to see which files are where. You can use COPY to get any particular file you want, off of one of the disks, without even having access to any of the other disks. But if you have a file that's larger than a disk, XCOPY can't do a thing. And it also wastes a lot of disk space. XCOPY copies files IN ORDER. Period. There is no way to make it do otherwise. If the next file in line is 300K in size and at the moment XCOPY is ready, there's only 299K of space left on that disk, you'll have to get out the next disk and leave that 299K on the first disk empty. Wasted. Also, XCOPY by itself, without some trickery, doesn't make multiple-disk copies. When the target disk runs out of space, XCOPY stops. It does not say "Insert the next disk and press any key to continue...." or anything like that. It just stops. Period. To solve this problem, what you have to do is A) Before you start, give the +A attribute to all the files you want to copy. B) Use XCOPY's /M switch, which tells it to only copy files that have the +A attribute, and turn off that attribute for each file it copies. C) When XCOPY quits with the "Insufficient disk space" message, you put in a new disk and execute the same XCOPY command again, with the /M switch again. Since the files that have already been copied had their A attributes turned off, and since XCOPY /M only copies files that have +A attributes, this means that now XCOPY is going to copy only the files that haven't already been copied. So it ends up working just like the BACKUP command in that regard, but only if you remember to ATTRIB +A all the files before you begin. Will both commands assign a sequential number to the diskettes (01, 02, 03, etc.) during backing up and also ask for the diskettes in sequential order when restoring the data back to the hard disk? BACKUP/RESTORE does that. XCOPY does not, since the disks it creates contains files that are in their original normal perfectly accessible format. Is there a way to use the BACKUP command so that it will not split files between diskettes? No. You wouldn't want it to do that at all. If it did that, there would be absolutely no reason for its existence whatsoever. A couple other things to mention. BACKUP puts all the files into one file on the backup disks. The only thing on the backup disks is one index file and one great big data file on each disk. That's why there is no wasted space on the disks, and that's why the files can't be retrieved from the disks without the RESTORE command. Since XCOPY stores the files in their original format, you can overwrite an old version of a particular file with a newer version of it, by simply copying the new version to the correct directory on the disk. With BACKUP, on the other hand, if you do an appended backup of a file, to the last disk in a backup set, and that disk already had the old version of that same file....the new version will NOT overwrite the old. The backup disk will contain BOTH versions of the file, so it's a waste of space! But you can't get the old version back! Even if you end up needing the old version back, you can't get it. RESTORE will restore the old version and immediately overwrite it with the new version, and there is no RESTORE syntax or switch that'll prevent that. So BACKUP wastes space by keeping two copies of the same file on the same disk, without the benefit of letting you have access to the older version if you ever need it again. But XCOPY doesn't let you keep multiple versions of the same file either, unless you keep them on separate disks (which BACKUP would also let you do). After several years as a PC user I have produced thousands of files. Most of them I keep saved at my hard disk or on diskettes. Not everything is important, but experience has taught me that it is difficult to say anything about the future. One day I will need the note I wrote in the summer 1987. A good backup makes it easy to update and keep a record of thousands of files. To an average user with a homeoffice like the one I've got, I will recommend a system, a routine, which is based on a three generations backup. During a period of three year I have used a routine that backup the hard disk every month. It's up to you how you will adapt the routine to your own needs. May be it's sufficient to make a main copy once a year. As I have mentioned, my system is based on a main copy every month. The main copy I used every month, took care of the files I wanted to erase. I didn't want them be included in my backup and then eventually restored. In addition to the main copy, I backed up parts of the files every week. As with the main copy I erased the files from this partial copy that I didn't want to keep for just a short period. Additionally I assign the value 0 to the place where the daily copy is kept, so it's kept to a minimum concerning diskettes. My daily backup was performed once and sometimes twice a day, and should only contain a few files so I didn't use the whole day to backup. I wanted to make an automatic routine of the backup job. You all know how easy it is to skip or forget boring backups, especially when your system has functioned without problems for months or may be years. But one day, sooner and later, your computer will have problems, it will stop working and you may face really problems with getting data from your hard disk. When it comes to losing my work I am a coward, I don't take risks. I want to run a safe system. I decided that backup should be an integrated part of my daily upstart. AUTOEXEC.BAT is the only batch file I have to execute every day. You should also backup your files as your last thing to do every evening. Fires usually starts at night, or water leakage. Below I present a way to manage your backup, a system I have tested for years. You will probably find it detailed, but it works and it takes good care of your important data. The batch file was written some years ago and is related to earlier versions of MS DOS than 6.0. The batch file uses the commands BACKUP, RESTORE, GETMONTH, GETDAY, DOW and call other batch programs. In your MS DOS manual you will find details upon how BACKUP and RESTORE works. The batch file uses three different switches: /s indicates that you want to copy subdirectories, /a that you add the files to be backed up to those already on the backup disk and do not erase saved files on the backup disk. /m back up only those files that have changed since the last backup. Run EDLIN or EDIT from the command prompt and specify the name SECURITY.FIL. I myself prefer Qedit as an editor to write my batch files. It provides many features that make batch programming easier and faster. Be accurate when you create your batch file. All files must be in the same directory, for example DOS. Comments on the files below: ---------------------------- 1) Don't miss spaces! When the files have been saved, see to that DEBUG resides in the DOS directory and type DEBUG setcopy.fil ECHO set partcopy=%partcopy% >> setcopy.fil ECHO set daycopy=%daycopy% >> setcopy.fil :notcopy BCOPY.BAT ========= @ECHO OFF REM BCOPY.BAT CLS COPY setcopy.fil+security.fil security.bat >nul security.bat SETCOPY.FIL =========== set maincopy=8 set partcopy=5 set daycopy=25 BCOPY.BAT and SETCOPY.FIL should be in root directory. The contents of SETCOPY.FIL must be adjusted every month. Decide on which weekday and date you want the routine to begin. It's important that the computers date is correct. DATES.SCR ========= n GETMONTH.com a 100 mov ah, 2a int 21 mov al, dh mov ah, 4c int 21 rcx a w n GETDAY.com a 100 mov ah, 2a int 21 mov al, dl mov ah, 4c int 21 rcx a w n DOW.com a 100 mov ah, 2a int 21 mov ah, 4c int 21 rcx 8 w q BACKUP1.BAT =========== @ECHO OFF REM BACKUP1.BAT IF /%1==/ GOTO SHOW REM %1 is not empty,no problems will occur when strings are compared IF %1==1 CD\ IF %1==1 BACKUP C: A: /s IF %1==1 GOTO END IF %1==2 CD\ IF %1==2 BACKUP C: A: /m IF %1==2 GOTO END IF %1==3 CD\ IF %1==3 BACKUP C: A: /m /a IF %1==3 GOTO END REM If %1 is true, the program moves to the end REM Display an error message ECHO YOU HAVE WRITTEN AN INVALID SWITCH!! :SHOW ECHO TYPE A 1 FOR A TOTAL BACKUP ECHO TYPE A 2 FOR A CERTAIN CHOICE BACKUP ECHO TYPE A 3 FOR A CERTAIN CHOICE BACKUP THAT WILL BE ADDED TO AN EXISTING DISK GOTO END :END The batch file is an unfinished example which can handle many parameters or none at all. I leave it to you my reader to complete it? It's a fine study to learn how IF sentences can enhance your batch programs and make them more flexible. Chapter 3: ================================================================= Chapter 4: Edit a batch program =============================== Two years ago, someone offered the following batch file, and I have found it to be indispensable. Like most other users, I keep all my batch files in one directory, and I used to have to type in the entire directory\pathname\filename.ext or change drives\directories just to edit a given batch file. With this BAT.BAT file placed in your batch file directory, you can edit any given batch file from any drive/directory. All that is required is to enter BAT FILENAME. No extensions are necessary. BAT.BAT ======= @ECHO OFF :: REM BAT.BAT :: REM I can edit ANY batch file in D:\BATCH from anywhere in any drive cls IF %1 .==. goto NOT q d:\batch\%1.bat goto END :NOT q d:\batch\ :END cls Notice that I use QEdit, and it is also in my path...... I really appreciate that people share batch files. Users that are new to computers often like to experiment with writing batch files. It's exciting when you can help someone else with a batch due to the fact that applications are scary enough for them. Chapter 5: Batch pipe problem ============================= Now and then I get questions about different batch problems. A frequently asked question is how we can run a batch file with the command MORE. Is there a way to get around " | more" not working to scroll output? @ECHO OFF for %%f in (%2) do find /i "%1" %%f Yes, each 'find' command is a completely different command, opening and closing the pipes. Here's how I would do it in regular dos. for %%f in (%2) do find /i "%1" %%f >> temp.x type temp.x | more Considering each 'find' operation is a separate command, the append '>>' symbol is necessary or else you only get the results of the last file in the list. for %%f in (%2) do find /i "%1" %%f The problem is that the MORE filter only works with one instance of STDOUT output at a time. If the output from any ONE of the FIND statements would make the screen scroll, you'd find that the filter does work--for that single FIND statement only. Try attacking this from another angle--direct all of the STDOUT output into a text file, then pass that text file through the MORE filter: del txt for %%f in (%2) do find /i "%1" %%f >> txt type txt | more If you don't want the "---" lines in your output, change the FOR..IN..DO loop to read for %%f in (%2) do find /i "%1"<%%f>>txt Yea, it's working nicely with both suggestions. Most people are aware of the '>' redirect command. But, they don't know that they can append text also with '>>'. Nice! I'll try modifying it also to get rid of the '---' header. @ECHO OFF for %%f in (%2) do find /i "%1" %%f I think it's because you only get one command after "do", in this case it's find. "more" gets lost in the shuffle. This is one of the serious drawbacks to DOS, as it's fairly simplistic as far as operating systems go. As a test, make a batch file with -just- find followed by more, like: find "hello" txtfile.txt | more ...to see if it works there. If not, then either "find" or "more" is the problem, otherwise it's "do". In any case, you may have to output your stuff to a file first, then "more" that to the screen. SEARCH.BAT ========== @ECHO OFF FOR %%f IN (%2) DO FIND /i "%1" %%f SEARCH1.BAT =========== @ECHO OFF FOR %%f IN (%2) DO FIND /i "%1" %%f >> temp.x TYPE temp.x | MORE SEARCH2.BAT =========== @ECHO OFF FOR %%A IN (*.*) DO FIND /i "%1" %%A >> TEMP.X TYPE TEMP.X | MORE SEARCH3.BAT =========== @ECHO OFF FOR %%A IN (*.*) DO FIND /i "%1" %%A >> TEMP.X TYPE TEMP.X | MORE DEL TEMP.X Chapter 6: Searching for files is often time consuming ====================================================== In this chapter we are going to look closer at different ways to look for files and specific text strings. If you are working with large data files, searching for certain text strings in giga- bytes of information you probably know how time- consuming it is and how much time it takes to find the files you are looking for. Every day I use different methods to find files where I have stored essential information. Normally I work in a Windows environment. Windows provides excellent methods to execute a search, find files, look for special documents that are stored some place on your hard disk. Still I prefer to search in plain MS DOS. It's faster, especially when I'm searching through hundreds, may be thousands of different files. Below is one of my favourites. I call it LAF.BAT (List all files). The logic in the batch file is simple, but with great functionality. I keep it in my batch directory and has defined the directory in my path. I can use it all over the hard disk. The syntax is very easy: LAF search string LAF.BAT ======= @ECHO OFF CHKDSK/V|FIND "%1" In the first line I turn off the command ECHO. I don't want to view the execution of the batch file. I'm only interested in the report. In the second line I use the options CHKDSK offers and /v that displays the name of each file in every directory as the disk ischecked. The list piped to the MS DOS command FIND. FIND looks through the list searching for the specific string you want to search for. We add the switch /i to the command FIND, so we don't have to worry about if the search is case-sensitive or not. If you ignore /i, the specified string of text must be written in capital letters. This is how MS DOS will display it. I hope you enjoyed it. Let's take a look at other batch programs. Let's take a closer look at the smart file below. ALL.BAT ======= ECHO OFF :START IF "%1"==" " GOTO END CLS ECHO *** Lines in *.bat that contain %1 *** ECHO FOR %%p IN (*.bat) DO FIND /c "%1" %%p ECHO PAUSE SHIFT GOTO START :END The batch file searches for a specific string of text in a specified file or files. The name of the files you are looking for is specified in the batch file. You are allowed to type several parameters. This method is useful if you want to search within the same group of files. In the example below, I search through all the batch files. Both the command FOR and SHIFT is used in the batch file to search for more than one string i several files. Below is a line by line description. _ Line 1 turns ECHO off _ The label :START sets the beginning of the command sequence you need to repeat. The label is the destination for the command in GOTO on line 11. _ The command IF controls whether the parameter is an empty parameter. If it is, the condition is met and the command GOTO will make MS DOS move on to the end of the batch file at line 12. _ Line 4 clears the screen and place the prompt at the top of the screen. _ The command ECHO in line 5 displays a message to the user. Line 6 displays a blank line. _ The command FOR searches every file with the suffix BAT, and displays the amount of lines with the string (" %1 "), which is the first specified parameter in the batch file All.BAT _ As line 6 line 8 displays a blank line. - Suspends processing of a batch program and displays a message that promptsthe user to press any key to continue. You can use this command only withinbatch programs. _ The command SHIFT in line 10 moves parameter one step to the left. _ The command GOTO returns MS DOS to the label :START. _ The label :END identifies the end of the batch file. (the destination for the command GOTO i line 3). To run ALL.BAT you must write the text, the words, the strings you are looking for as parameters. Notice! The command FIND is case-sensitive. Say you want to search for the words ECHO, COPY and message. Use the following syntax: ALL ECHO COPY melding ALL clears screen, searches the suffix BAT for the word ECHO, displays the amount of lines and stops. You are asked to press any key and the batch file carry on and searches the files for the word copy and displays the result. The batch process repeats until all the words you have specified have been found. /c displays the amount of lines containing the given string i each file. The switch is one of the command FIND'S many options. To end the batch file you must press CTRL-C and answer Y for Yes. FIND.BAT ======== Somewhere on your hard disk you remember that one of your most important files is located, but exactly where is the question? FIND.BAT use the switch /v belonging to the command CHKDSK. The switch displays a list of all existing files on the hard disk. If redirects the list to a file you can produce a fast search with with the command FIND. First time you run FIND, the program will create a file called CATALOG.DAT in the root directory. Below is an example how you can use it. C:\>FIND BAT The execution of the command will make a list of all batch files on your hard disk. Notice the FIND.BAT doesn't take wildcards like * or ?. In addition to search for files you can use FIND.BAT to check if there are more copies of the same file in different directories. All you have to do is to type the file name and FIND will immediately list all file names that match. The disadvantage is that FIND can't automatically register changes on your hard disk. To upgrade \CATALOG.DAT you just have to use the parameter new in the search string. If you are depending on an upgraded list or maybe you need to search only once, you can use the technique this way. CHKDSK /v | FIND ".BAT" You redirect the outprint directly to FIND that will display only the lines containing the string "BAT". Since it takes at least the same time to run the command CHKDSK it will always pay to use \CATALOG.DAT if you intend to repeat the search. Users that run the version 4.0 of MS DOS it's much easier. The MS DOS command FIND has been improved so you can search for files all over your hard disk. The command FIND *.BAT will list all batch files, but not so fast as our batch file. FIND.BAT ======== @ECHO OFF IF NOT "%1 "==" " GOTO OK :INSTR ECHO ECHO Command ECHO FIND {string} [new] Find the file name containing the {string} ECHO {string} must be UPPER case ECHO The option NEW updates the catalog. GOTO END :OK IF "%2"=="ny" GOTO CHKDSK IF NOT "%2"==" " GOTO INSTR IF EXIST \CATALOG.DAT GOTO FIND_FILE :CHKDSK ECHO Updates the catalog.... CHKDSK /v >\CATALOG.DAT ECHO  :FINN_FILE FIND "%1" \CATALOG.DAT :END _ Line 2 skips the instructions if you specify at least one parameter. _ Line 4-8 displays instructions on how to use the batch file. _ Line 11 executes CHKDSK if the parameter NEW is specified. _ Line 13 jumps directly to the search routine if the file \CATALOG.DAT exists. _ Line 16 runs the command CHKDSK and redirects the outprint to the file \CATALOG.DAT. _ Line 17 blanks the outprint from line 15. _ Line 19 look for the specified string in the file \CATALOG.DAT LOOKFOR.BAT =========== ECHO off CLS ECHO ***LINES I %1 CONTAINING %2*** ECHO for %%p in (%1) do find "%2" %%p To show all lines containing a certain string LOOKFOR.BAT can point out the file you must search and the string you must specify. Each line containing the string in the file, will be displayed. Wildcards are allowed to search in groups of files. The job is done in the last line of the batch file. The previous line clears the screen and displays a title. The command FOR in line 5 makes the command FIND be repeated for each file name stated in your first parameter when you type your LOOKFOR.BAT command. The command FIND looks for the string you specified as the second parameter. To display each line containing the word "NOT" in all files in current directory you must type: LOOKFOR C:\SHAREWARE\PLENTY??.* NOT Chapter 7: Customizing the command dir ====================================== Next to the command COPY DIR is maybe the most common command you use. Every day we need to list directories, find files with specified names or file extensions. The command DIR has really improved since the earliest MS DOS versions and provides several useful different options. Very often you find yourself listing directories containing directories with hundreds of files and it's impossible to read the screen. The switch /p is very handy. When you need to look at your files in wide format the switch /w provides as many as five file names or directories. Of course, the command DIR offers several useful possibilities, but the human nature needs changes and searches always for new ways to do things. The imagination and the creativeness start working. There will always be people that are looking for that special command that does not exist. With our batches we can create them. How is it possible to list all files in a directory except those that have got a specific file extension? The problem has different solutions. For example you can write a program like LAFUEXT.BAT =========== @ECHO OFF DIR | FIND /i /v %1 > dirfile TYPE dirfile | more (Lists all file without the extension.) The program starts as usual with turning ECHO OFF. DIR lists the directory and redirects the list to FIND. FIND has offers the following options: /i means that FIND will be case sensitive. /v displays all lines in the file not containing the specified string. The result is redirected to a file we call "dirfile", and the command TYPE displays the contents of dirfile screen by screen. The command MORE one screen of information at a time. We can also do it in another way. LAFUEXT1.BAT ============ @ECHO OFF IF %1. ==. GOTO END DIR | FIND "%1" /v :END In this example we solve the problem with a little help from a simple IF-sentence. If %1 contains a file extension the program jumps to :END. The rest will be displayed without the specific string. We can also solve the problem by using the command ATTRIB, a command which is not very often used, and as a lot of batch files offers excellent functionality. LAFUEXT2.BAT ============ @ECHO OFF ATTRIB +h %1 DIR ATTRIB -h %1 This is what happens: ATTRIB puts the files with the specified extension to hidden. DIR won't list hidden files. The result is a list containing all file except those with a specified file extension. There is also a rather handy tool that is capable of solving the task. You can use NO.COM together with ordinary MS DOS commands. NO.COM ====== Copy the script file. NNO.ZIP E100 FC BB 03 00 BF D4 01 BE CC 01 33 C9 AD 86 CC AA FE C0 E2 FB 4B E115 75 F5 B9 FF FD BA 20 02 52 B4 3F CD 21 5F 72 60 8B F7 50 8B C8 E12A B0 2A F2 AE 75 55 B0 0D F2 AE 87 F7 BB 00 01 B2 04 AC 3C 2A 72 E13F 62 74 46 57 BF D2 01 B9 40 00 8A E1 F2 AE 5F 75 35 FE C1 2A E1 E154 88 27 43 FE CA 75 E0 56 BE 00 01 AD 86 C4 8B D0 AD 86 C4 5E B1 E169 02 D2 E0 D3 E0 D2 E2 D3 EA D0 E1 D1 EA D1 D8 E2 FA 86 C2 AA 8A E17E C4 AA 8A C2 AA EB B1 BF 20 02 58 33 D2 F7 D8 13 D2 F7 DA 33 DB E193 8B CA 8B D0 B8 01 42 CD 21 8B 0E CA 01 CC AC 3C 0A 75 FB AC 57 E1A8 BF D2 01 B9 40 00 8A E1 F2 AE 5F 75 D0 FE C1 2A E1 86 E0 32 E4 E1BD 8B 1E CA 01 03 D8 89 1E CA 01 E9 6C FF 00 00 30 0A 41 1A 61 1A E1D2 2B 2D G=100 W220 Q GXDPlus 1.0 *XXBUG20--00000422--18021994--964D7791------------------NO.ZIP nI2g1--E++U+6++++e-HLxixSdE6++C+0+++4++++HYwiEoxBDJ1jGpBT51 vbSXSrFUM3 nJfukQwgWBXIf2DALmhKYfAqM98dZnCre9amvQbQL9EcaEXKjv0wcG97SK3zlWlTQJ gn- n6Uit3TeWLdIYp3oHYMq6aihqbB8-1rnCwrmStzCQYxN-aVg8wimUKo15HnLIcwjgk2-B nVyAuuoQxULsDurSnjY32QvIJe6Tb-ba5pwisI5wEoKs5vq5k30DQt1kiJ42ByUH5XINY nhe+-3XB1X-AtCOzLsLCV8oACf4E2VjRTfH7Pw-11iDmckq737qffY8a6bT2tCNtbb+6u nXTL6WUq8S0z56SkGr973+cTQf6gdIioS1yRo00nbqonLvq4wFNWqb1zTPivsVyZFRJA 9 nq1eMgzNoohhLCmtDgNDeN8eNwCyB-u0YZmYNDKjS8TmMykNX4d0RGgLDkQEkq 3+IJQW9 nbveJNHKEBxzBnFb6o0rM4B1wJzItctDqmlHN9XIybPMrYA8VGNjsQvGr2DfS7bL7J1k A nyQT470PogHNgONaqHzO70uOriEZXQX9QiUd5AiH120-1ldG2keLnLQElSfkODAf1Q4 I- nXdKdi2e6gH6B2JwiYGdYGgGOi62ojN5AAiIrhCk4ka4w7RqeWjAOED-YoohS4ly5uFcp nwOR2GEBJikMZGqMlr9cCBwIslvGxY7pupIa+XGUs8JDrmfDEi-W3i7pFNkbZ1V+fpy 3k n0V1WmYVepzzYIYMuWxzm+j6qPIFP1Ile6UTXGz-6e+I6hCpWH+RmHuvp0LdXAe OeqObA npt3tLOLqE4bsW7sEDnnDkmXcZealpt4DYKHYjMXFyxg95q+PDvbtyHC3KO+Mk0U CIqFY n77OhkNKXMjoe3AjLcGpV6ALTmXtUuJDqU+hFEAjIkMIRvu6EBtSy98QaEfRJ2DWJy UhE nGkA23++0++U+OVtD5-lgExSr++++tE++++M+++-CHmt2HoDXtJ7EID-9n2 qpIj1nprDq nxyLZsiI880oem0w40XbatCGL3miYJWHbZ8NYteIf70eYNSOY3VSY7WiY3SLb8dFYd0 cY n7dRYtiQdt8Q-NNDnQrAHwp7+VWU2JyOJ73O+n2JcUgcfF-QY3U2h9IYh8cs38LOhG Akh nm+2vEY399wcnEA53pET6oU8P-+DVaHYt0WadCI-x0cZ+7hVMVOHG2e+vUCtJ8A wgmE+u n+eExhO6YBOwMu0uE+E-EGk203++I++6+0++++8UIpzPjLeI0++1U+U++- U++++++++++ n+0++++++++++HYwiEoxBI2g-+VE+3++0++U+OVtD5-lgExSr++++tE ++++M+++++++++ a+E+U++++mE6++2tD9YFDEp-9-EM++++++U+0+4U+++0Y+k++++ ++ *XXBUG Version 2.20 by Chad Wagner Execute the following command DEBUG < NNO.ZIP and you have become the happy owner of a new DOS tool. You have to be a registered user of PKUNZIP.EXE for unpack the file. You will receive NO.COM and NO.DOC which is a short user reference. If you register your copy of the Run Batch Run Book you will receive along with your order a companion disk containing my enhanced DIR command XDIR. Chapter 8: How can a batch program answer Y for yes =================================================== DELETE displays the following question when you executes the command: C:\> DEL *.* All files i directory will be deleted! Are you sure (Y/N)? One line of a batch file can't be executed until the previous line is DONE. A batch file that says DEL *.* and then Y will execute the DEL *.* command and then when that's OVER WITH, THEN it'll execute a Y command. The Y doesn't do anything; isn't even READ by DOS, until after the DEL command is FINISHED. So by the time DOS sees the Y, the DEL command is over and the Y will get executed as a command. So "Bad command or filename" will be the result, unless you happen to have a program named Y on your system. A batch file is not a list of keystrokes that'll get typed as if you were typing them at the keyboard. It's a list of COMMANDS that get executed, one by one, separately from each other, as if you were typing each one at each successive C:\> prompt. Having DEL *.* in a batch file will have the exact same effect as typing DEL *.* at the command line. Regardless of what commands might be in the batch file before or after. A command line has to be complete in and of itself, at the command line, in order for it to be complete in a batch file. The commands that come before or after it don't affect it. ECHO Y | DEL *.* works in the batch file because it works at the command line. Now there's one exception, of course. A program called a keyboard stuffer. There are several in existence. PC Magazine's KEY-FAKE and 4DOS's KEYSTACK, etc. Such programs stuff keystrokes into the keyboard buffer. So that the next program that executes, that wants a keystroke or some keystrokes, will find that "you" have already "typed" them (or so that program will THINK). If you used a keyboard stuffer to stuff a "Y" into the keyboard buffer before your DEL *.* command in your batch file, then it WOULD effect the DEL command, in contradiction to what I said above. The DEL command would find Y in the keyboard buffer and think you typed it, because the previous command in the batch file (the keyboard stuffer program) had put it there before the DEL command executed. It works the same way as ECHO Y | DEL *.* with a couple exceptions. 1. It would work for darn near any program, instead of only those that take input from what's called Standard Input, like DEL does. Because the | (pipe) symbol takes the first program's Standard Output (the ECHO command above would be sending a Y to Standard Output) and pipes it as Standard Input to the program after the | symbol. So DEL gets its Y from Standard Input. But some programs look directly at the keyboard to get their input, instead of using Standard Input. For such programs, the ECHO Y | trick won't work, but a keyboard stuffer program will. 2. Since it doesn't involve redirection of Standard Input, it works for programs that are going to want more input than just what's stuffed. If you used the ECHO X | PROGRAM trick to send one keystroke to a program that wanted five keystrokes, you'd have to reboot your computer. Because the program would wait all day for its other four keystrokes to come from the same location the first one had come from! No matter what you typed at the keyboard, it would have no effect because the program had been more or less told to ignore the keyboard! Standard Input had been redirected from the keyboard to the ECHO command. So the ECHO command is the ONLY place that program is going to take its input from, and the ECHO command only sent one keystroke so that's all the program gets! That program will never do anything further so you have to reboot! But a keyboard stuffer doesn't cause that problem because it doesn't redirect Standard Input the way the | symbol does. It just stuffs a keystroke (or several keystrokes) into the place where Standard Input (or any other kind of input) comes from the keyboard buffer. So....the ECHO X | WHATEVER trick is good for some things, but not all. And a batch file just simply can not do what you were asking, without the help of a keyboard stuffer program which you use to send the keystroke before you execute the program that wants the keystroke not after that program is finished. From time to another you need to erase more than one directory. This is very often a tedious job. Now your fantasy starts working. You construct a useful batch. After a while you are in charge of some useful tools. Ooops! Did I say in charge? Well, below I will present to you a rather dangerous tool that may, if you don't watch out, delete the total hard disk. Let's start working. This is the basic lines. ERASE.BAT ========= @ECHO OFF CLS DEL *.* When you run the batch program you have to answer Y/N. If you have planned to erase all the files in the directory, this turn out to be a rather heavy job. We don't want the warning. We want action: The directory is about to be erased. In the batch file ERASE1.BAT, you will get no more questions. ERASE1.BAT ========== @ECHO OFF CLS ECHO Y | DEL *.* By redirecting the Y through a pipe to the command DEL we solve the problem. You can also use another method. ERASE2.BAT ========== @ECHO OFF ECHO Y > ANSWER DEL *.* < ANSWER The batch program creates a file called ANSWER. The files contain Y and ENTER that DEL *.* needs. The Y is redirected to the command DEL and everything is all right. The smart thing is that the file ANSWER will be deleted as well, and everything is still all right because DEL has already read it. If you want to see how it runs, use REM to let MS DOS leave out ECHO OFF. Imagine there was a program that would repeat the command you just have executed. Imagine how it moves from one directory to directory. Lovely, isn't it? And the best thing is: you can have it. You can make it yourself by using Scan codes. REPEAT.SCR ========== This little program is created to repeat another command in the subdirectories. It starts from the directory where you first typed the command and continues to the very end. This is how the syntax looks like: C:\> REPEAT ERASE2 As you probably have understood at this moment the command will delete all files in the subdirectories below. It's a devil! You may use it with many different MS DOS commands, DIR, TYPE, etc. If you run it carelessly it is a very dangerous command. Not so that it will hurt you or do you any harm, but it could course a great deal of unnecessary work. My advice is that you better think twice. Plan how you will use it. Here is the script file, REPEAT.SCR: N REPEAT.COM E 0100 E9 AD 00 0D 0A 52 45 50 45 41 54 20 2D 3E 20 20 E 0110 20 20 20 00 3A 5C 00 00 00 00 00 00 00 00 00 00 E 0120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 0130 00 00 00 00 00 00 00 00 00 1A 4E 65 65 64 73 20 E 0140 44 4F 53 20 32 2E 30 20 2B 24 41 6C 6C 6F 63 61 E 0150 74 69 6F 6E 20 50 72 6F 62 6C 65 6D 24 53 57 45 E 0160 45 50 3A 20 43 4F 4D 4D 41 4E 44 20 50 72 6F 62 E 0170 6C 65 6D 24 53 57 45 45 50 3A 20 41 62 6E 6F 72 E 0180 6D 61 6C 20 45 78 69 74 24 00 00 00 43 4F 4D 53 E 0190 50 45 43 3D 00 00 00 00 00 00 7D 00 00 00 5C 00 E 01A0 00 00 6C 00 00 00 2A 2E 2A 00 2E 2E 00 8F 04 00 E 01B0 B4 30 CD 21 3C 02 73 09 BA 3A 01 B4 09 CD 21 CD E 01C0 20 86 C4 A3 89 01 BC 8F 04 BB FE 09 B1 04 D3 EB E 01D0 B4 4A CD 21 73 05 BA 4A 01 EB E0 06 BB 2C 00 8E E 01E0 07 2B FF BE 8C 01 FC 26 80 3D 00 74 14 56 57 B9 E 01F0 08 00 F3 A6 5F 5E 74 0F 2A C0 B9 FF FF F2 AE EB E 0200 E6 07 BA 5D 01 EB B4 83 C7 08 89 3E 94 01 8C 06 E 0210 96 01 8C 06 98 01 8C 0E 9C 01 8C 0E A0 01 8C 0E E 0220 A4 01 07 A0 80 00 04 03 A2 7D 00 C6 06 7E 00 20 E 0230 C7 06 7F 00 2F 43 B8 00 33 CD 21 88 16 8B 01 2A E 0240 2D B8 01 33 CD 21 BA 3C 03 B8 23 25 CD 21 B4 19 E 0250 CD 21 04 41 A2 13 01 BE 4F 03 2A D2 B4 47 CD 21 E 0260 BE 16 01 2A D2 B4 47 CD 21 BE 03 01 FC AC 0A C0 E 0270 74 08 8A D0 B4 02 CD 21 EB F3 B9 F4 01 B4 0B CD E 0280 21 E2 FA 81 3E 89 01 0A 03 72 0C B2 0D B4 02 CD E 0290 21 B2 0A B4 02 CD 21 BB 98 01 C5 16 94 01 2A C0 E 02A0 B4 4B CD 21 8C C8 8E D8 8E C0 8E D0 BC 8F 04 9C E 02B0 2A D2 B8 01 33 CD 21 8A 16 13 01 80 EA 41 B4 0E E 02C0 CD 21 9D BA 5D 01 72 0C BA 15 01 B4 3B CD 21 73 E 02D0 0A BA 74 01 B4 09 CD 21 EB 62 90 8B 16 AD 01 B4 E 02E0 1A CD 21 80 3E AF 01 00 75 0C BA A6 01 B9 10 00 E 02F0 B4 4E CD 21 EB 04 B4 4F CD 21 72 25 8B 1E AD 01 E 0300 F6 47 15 10 74 F0 83 C3 1E 80 3F 2E 74 E8 8B D3 E 0310 B4 3B CD 21 83 06 AD 01 2B C6 06 AF 01 00 E9 3F E 0320 FF 81 3E AD 01 8F 04 74 13 83 2E AD 01 2B C6 06 E 0330 AF 01 FF BA AA 01 B4 3B CD 21 EB 9F BA 4E 03 B4 E 0340 3B CD 21 8A 16 8B 01 B8 01 33 CD 21 CD 20 R CX 24F W Q Type the whole script in your editor. My favourite is SEMAFOR'S QEDIT, PLAIN ASCII-text. Then execute the following command to get REPEAT.COM. DEBUG < REPEAT.SCR Put the new command where you keep your utilities. You are now probably the happy owner of a new and very useful tool. But don't blame me if you erase important files. Chapter 9: Batch files can be used with memory and RAM ====================================================== It's always exciting when you find new unconventional ways of using batch files. I usually test these programs immediately to see how I can use them in my work. Below I will show you some interesting samples. Sometimes you need to find out wether a program is loaded into memory or not? Here is a way to do it, it's not so very elegant, but it works. ISRES.BAT (Is resident) ======================= @ECHO OFF REM ISRES.BAT - Tests if a program is loaded into memory REM by using MEM/C SET ISRES=N MEM /c > %temp%memtxt FIND "%1" /i < %temp%memtxt > %temp%$$there COPY %temp%$$there %temp%isthere > nul IF EXIST %temp%isthere SET ISRES=Y IF %isres%!==Y! ECHO "%1" the driver is resident. IF %isres%!==N! ECHO "%1" The driver is NOT resident. DEL %temp%??there > nul DEL %temp%memtxt > nul Now, what happens in the file? As usually we start the program by turning ECHO OFF, we don't want the command lines displayed. The second line contains comments that explain what the program does. In the third line a variable is sent to the environment which put ISRES=N. When MS DOS discovers a named parameter in a a batch program, the system looks immediately in the environment for an entrance assigned a value: SET ISRES=N In the fourth line MS DOS executes the command MEM with the switch /c. The /c is short for /classify. It lists the programs that are currently loaded into memory and shows how much conventional and upper memory each program is using. MEM /classify also summarizes overall memory use and lists the largest free memory blocks. You can use the /classify switch with /page but not with other MEM switches. You can abbreviate /classify as /c. The report is redirected to a directory called temp and a file called MEMTXT is created. In the fifth line FIND takes over the command. The switch /i make the command case-sensitive. The string I'm looking for in my case is "HIMEM". The file FIND shall search is MEMTXT, the redirecting sign < tells FIND where to search. The result is redirected to C:\WINDOWS\TEMP$$THERE. $$THERE is not so easy to understand, but I copy $$THERE to ISTHERE. I don't want any messages that says that 1 file (s) copied and is therefore redirected to nothing, > NUL. In the next line the command IF EXIST tests if ISTHERE exists and if it does the result is that the SET VARIABLE in environment is set Y with SET ISRES=Y. I line eight and nine we get the message: If the variable is set to Y, ECHO shows : "HIMEM" driver is resident. If the variable is set to N, ECHO displays "HIMEM" driver is NOT resident. When the job is done the batch program deletes the files ??THERE and MEMTXT. The syntax is simple: Type ISRES prog_name. If "prog_name" exists the report from MEM /c the ISRES variable will be set to Y, or will continue to N. Notice that MS DOS doesn't copy 0-byte files. If the search string does not exist in the report from MEM /c, the file $$THERE won't be copied to ISTHERE, and the line IF...EXIST will fail. RAMDRIVE.BAT ============ Very simple you can define a RAM-disk as a diskette where the files isn't stored physically on a magnetic disk, but temporary in the computer's memory. From a user's point of view a RAM-disk behaves just like other diskettes, but since the computer doesn't need to read disks a RAM-drive is very fast. But very few make use of the possibility. The reason is that the RAM-drive use memory wether you need it or not, and you lose the content when you turn off the computer. A much better alternative is a so called CACHE-buffer, which acts as an "intelligent" RAM-disk. RAM-drives are created in the CONFIG.SYS file by typing the command DEVICE=RAMDRIVE.SYS. In addition you have to specify the disksize, the sectorsize and the number of files and directories you can create in the RAM disk's root directory. RAMDRIVE or VDISK is allocated automatically in the first empty logical location. If your computer is equipped with to diskette drives (A and B) the RAM-drive will be C. If your computer has got a hard disk the RAM drive will be D. RAMDRIVE.SYS has four parameters: DEVICE=RAMDRIVE.SYS and two switches /e and /a, /e Creates the RAM disk in extended memory instead of in expanded memory or conventional memory. /a Creates the RAM disk in expanded memory instead of in extended or conventional memory. Syntax DEVICE=[drive:][path]RAMDRIVE.SYS [DiskSize SectorSize [NumEntries]]] [/E | /A] Parameters [drive:][path] Specifies the location of the RAMDRIVE.SYS file. DiskSize Specifies how many kilobytes of memory you want to use for the RAM drive. For example, to create a 640K RAM drive, specify 640. If you don't specify an amount, RAMDrive will create a 64K RAM drive. You can specify a value from 4 to 32767. However, you cannot specify more memory than your system has available. SectorSize Specifies the disk sector size in bytes. The size can be 128, 256, or 512 bytes. (If you include a SectorSize value, you must also include a value for DiskSize.) Generally, you should use the default sector size of 512 bytes. NumEntries Limits the number of files and directories you can create in the RAM drive's root directory. The limit can be from 2 to 1024 entries; the limit you specify is rounded up to the nearest sector size boundary. If you do not specify a limit, you can create up to 64 entries in the RAM drive's root directory. (If you include a value for NumEntries, you must also include values for DiskSize and SectorSize.) If there is not enough memory to create the RAM drive as specified, RAMDrive will try to create it with a limit of 16 directory entries. This may result in a RAM drive with a different limit from the one you specified. For RAMDrive to use extended memory, your system must be configured so that it provides extended memory, and a DEVICE command for the extended-memory manager (such as HIMEM.SYS) must appear in your CONFIG.SYS file before the DEVICE command for RAMDRIVE.SYS. In general, it is best to create a RAM drive in extended memory if your system has extended memory. For RAMDrive to use expanded memory, your system must be configured so that it provides expanded memory, and the DEVICE command for the expanded-memory manager (such as EMM386, 386MAX, CEMM, or QEMM) must appear in your CONFIG.SYS file before DEVICE command for RAMDRIVE.SYS. DEVICE=C:\DOS\RAMDRIVE.SYS 128 256 16 or create a RAM-disk with 1.5 Megabyte, 512-byte sectors and 200 file names in extended memory: DEVICE=C:\DOS\RAMDRIVE.SYS 1500 512 200 /E The use of RAM-disk can be divided in two groups. To optimize a certain process or you need to increase the speed generally. A typical example of optimizing a certain process is for example a program that reads two files at the same time and you get a disk trashing. This leads to that the reading head jumps between the to files as they are read into the computer. In addition you sit and wait for the computer to finish. If you place at least one of the files on a RAM-disk you avoid the problem. If you use the technique on similar problems you can achieve a much better efficiency and you can automate it. Think of a routine that automatically copy a file to a RAM drive, runs the job and maybe copies the file back and removes it from the RAM drive. You can also speed up DOS by using external commands or useful tools with a RAM drive. For example in AUTOEXEC.BAT which the computer runs each time you turn it on. The RAM-disk should be written in the beginning of the PATH-variable. To make it easier to use a RAM-disk you can run the batch file below, RAMDRIVE.BAT. The file will create and remove a RAM-disk to your needs. You don't have to make changes in the CONFIG.SYS directly. The RAMDRIVE.BAT uses to commands called REPLY and RESET. REPLY stops and waits for you to press a key and returns an ASCII-code. If you press any of the special keys on the keyboard it returns the enhanced ASCII-code (Extended ASCII). RESET reboots the computer as (Ctrl-Alt-Del) so the new changes can take place. The can make the programs by using scan codes and compile them in DEBUG. Here is how to do it: Create a file called .SCR-file and redirect it to DEBUG: DEBUGnul IF EXIST ramdrive.log DEL ramdrive.log IF EXIST log.new DEL log.new IF EXIST config.new DEL config.new GOTO RESET :RAMDRIVE IF not "%2"=="" IF not "%3"=="" IF not "%4"=="" GOTO OK ECHO You must specify at least three parameters to the ramdrive GOTO END :OK IF %1==none COPY config.$$$ config.new >nul IF %1==new COPY config.sys config.new IF %1==add IF EXIST RAMDRIVE.log COPY RAMDRIVE.log log.new >nul ECHO DEVICE=C:\DOS\RAMDRIVE.sys %2 %3 %4 %5 >>config.ref COPY config.ref+config.$$$ config.new >nul IF "%5"=="" ECHO %2 Kbyte disk with %3-byte sectors and max %4 files>>log.new IF "%5"=="/E" ECHO %2 Kbyte disk with %3-byte sectors and max %4 files in extended memory>>log.new :RESET ECHO The following RAMDRIVES are now defined: IF EXIST log.new type log.new IF NOT EXIST log.new ECHO *** NOTHING *** ECHO Press F1 to continue or any other key to cancel. REPLY IF ERRORLEVEL 59 IF NOT ERRORLEVEL 60 GOTO DO_IT ECHO *** CANCELLED *** IF EXIST log.new DEL log.new GOTO STATUS :DO_IT DEL config.sys REN config.new config.sys IF EXIST log.new COPY log.new Ramdrive.log >nul RESET :STATUS ECHO Active RAMDRIVE: IF EXIST RAMDRIVE.log type RAMDRIVE.log IF NOT EXIST RAMDRIVE.log ECHO *** NOTHING *** :END Before you run RAMDRIVE.BAT you must copy the original CONFIG.SYS to CONFIG.$$$. Then you type RAMDRIVE. Both REPLY and RESET must be in the path. RAMDRIVE.BAT must be located in the root directory. Chapter 10: To remove files accidentally extracted ================================================ DEZIP.BAT ========= @ECHO OFF :DEZIP.BAT - Removes file accidentally extracted to the wrong directory. : (Type "DEZIP /?" (not the quotes) for brief instructions). ECHO. :Check user parameters------------------------------------------------ if (%1)==() goto SYNTAX if (%1)==(?) goto SYNTAX if (%1)==(/?) goto SYNTAX if (%2)==() goto SYNTAX if (%2)==(?) goto SYNTAX if (%2)==(/?) goto SYNTAX :Check target directory ------------------------------------------------ if not exist %1\nul echo Error: %1 does NOT exist! if not exist %1\nul goto SYNTAX if not exist %1\*.* echo Error: %1 does NOT contain any files! if not exist %1\*.* goto SYNTAX :Check for ZIP file ---------------------------------------------------- if not exist %2 echo Error: %2 does NOT exist! if not exist %2 goto SYNTAX :Check for PKZIP.EXE --------------------------------------------------- ctty nul ver|pkzip>temptemp ctty con copy temptemp+,,>nul if not exist temptemp echo Error: PKZIP is NOT available! if not exist temptemp goto SYNTAX :Do it! ---------------------------------------------------------------- pkzip- -fm %2 %1\*.*>nul if errorlevel 18 echo Error: PKZIP reports it is unable to open 1 or if errorlevel 18 echo more specified files. if errorlevel 18 goto SYNTAX if errorlevel 17 echo Error: PKZIP reports there are too many files if errorlevel 17 echo for the amount of memory available. if errorlevel 17 goto SYNTAX if errorlevel 16 echo Error: PKZIP reports bad or illegal parameters if errorlevel 16 echo specified. if errorlevel 16 goto SYNTAX if errorlevel 15 echo Error: PKZIP reports the ZIP file is read-only if errorlevel 15 echo and can not be modified. if errorlevel 15 goto SYNTAX if errorlevel 14 echo Error: PKZIP reports your disk is full. if errorlevel 14 goto SYNTAX if errorlevel 13 echo Error: PKZIP reports the specified ZIP: %2 if errorlevel 13 echo was NOT found. if errorlevel 13 goto SYNTAX if errorlevel 12 echo Error: PKZIP reports NO files were found to if errorlevel 12 echo add/delete to/from ZIP file. if errorlevel 12 goto SYNTAX if errorlevel 11 echo Error: PKZIP reports Insufficient memory. if errorlevel 11 goto SYNTAX if errorlevel 3 echo Error: PKZIP reports error in ZIP file. if errorlevel 3 goto SYNTAX if errorlevel 1 echo Error: PKZIP reports bad file name or file if errorlevel 1 echo specification. :SUCCESS --------------------------------------------------------------- echo Any files that were in subdirectory: %1 echo with the same filenames as files in: %2 echo have been successfully removed from: %1 echo. echo. goto CLEANUP :SYNTAX ---------------------------------------------------------------- echo. echo Name: DEZIP.BAT v1.1 - Vernon Frazee 06/91 echo. echo Purpose: Removes files accidentally unZIPped to the wrong directory. echo. echo Syntax: [d:][\path\]DEZIP d:\path d:\path\filename.zip echo. echo Where: "d:\path" is the drive:\directory containing the files echo you want DEZIP to remove. echo. echo "d:\path\filename.zip" is the ZIP file containing the echo filenames you want removed from "d:\path". echo. echo \/--------------[ Any files in this ZIP echo Example: DEZIP C:\LOTUS D:\NEW\FOO.ZIP echo /\------------------------[ remove from this DIR. echo. echo English: Remove all the files from the C:\LOTUS directory that are echo duplicates of any files found in D:\NEW\FOO.ZIP. echo. echo Note: PKZIP.EXE must be available somewhere in your PATH. echo. :CLEANUP --------------------------------------------------------------- if exist temptemp del temptemp :END ------------------------------------------------------------- -vjf- Chapter 11: Choice ================== While experimenting with DOSSHELL I pressed the Enter key with a Batch File highlighted. Of course the file was executed even though I didn't really want to defrag my drive at the moment. Associating this batch file with the .BAT extension provides the option to Edit, Run or Cancel. Seems like this could also be cloned to send .DOC files to the Word Processor, ASCII Editor, or Viewer; view or extract archives; etc.. MULTIJOB.BAT ============ @ECHO off rem CLS bright white on blue (ansi) ECHO ECHO ===============================[Multi-Associate]=========================== ECHO Please select action to take with: %1 ECHO. CHOICE /c:erc Edit, Run, or Cancel IF errorlevel 3 GOTO clear IF errorlevel 2 GOTO run IF errorlevel 1 GOTO editor :editor ECHO edit %1 GOTO end :run ECHO CALL %1 GOTO end :clear ECHO :end rem -- multiple-association batch file for DOSSHELL -- Chapter 12: How to get the system date ======================================= In this chapter we will discuss among other topics how to get the system date, using only three letters and without a complicated batch file with labels and GOTO. We start with a simple COM program called MON.COM. created with scan codes. Write the following into your editor. My favourite is Qedit. MON.SCR ======= N MON.COM A 100 MOV AH, 2A INT 21 MOV AL, DH MOV AH, 4C INT 21 R CX A W Q ;int 21h/2a Get System Date ;returns: ; al day of week (0-6) ; cx year (1980-2099) ; dh month (1-12) ; dl day (1-31) mov ah,2ah int 21h mov al,dh ; we send the month in errorlevel mov ah,4ch int 21h Then the batch file. MON.BAT ======= @echo off mon if errorlevel 1 set mon=jan if errorlevel 2 set mon=feb if errorlevel 3 set mon=mar if errorlevel 4 set mon=apr if errorlevel 5 set mon=may if errorlevel 6 set mon=jun if errorlevel 7 set mon=jul if errorlevel 8 set mon=aug if errorlevel 9 set mon=sep if errorlevel 10 set mon=oct if errorlevel 11 set mon=nov if errorlevel 12 set mon=dec Technically what we have here is an exception to the high -> low testing of errorlevel. In our example it works because we are constantly overwriting a single variable from the lowest errorlevel to the one that you want. Although it works, I believe it is poor programming practice because: 1) it is an exceptional case and programming techniques should be as consistent as possible both for the benefit of the programmer, who does not have to consider "is this an exception and therefore I can do another way if I want to", and more importantly for anybody else who may need to read, and or maintain, the code. 2) it is less efficient since you are consuming extra memory cycles for each errorlevel below the one you want by rewriting the variable each time. I guess I have been in this business too long, but I continue to look with amazement at the bloat that has taken place in both program size and machine cycle capability to perform them. There have been several batch files that will set a date or time in an environment variable. They are smaller and do not require any additional unique programs or capabilities other than what can be done with plain DOS. Despite all of the above, I think the program is a clever use of both assembly language and a batch file. Here is another batch file which gets the system date. GETDATE.BAT =========== : Sets the date as an environment variable. ECHO @ECHO OFF > C:\CURRENT.BAT ECHO @SET TODAY=%%4 >> C:\CURRENT.BAT ECHO. | DATE | FIND "Current" > C:\GDATE.BAT CALL C:\GDATE.BAT < C:\CURRENT.BAT DEL C:\CURRENT.BAT > NUL DEL C:\GDATE.BAT > NUL This puts the current date as mo-da-year in the environment variable TODAY. ECHO @ECHO OFF > C:\CURRENT.BAT ECHO @SET TODAY=%%4 >> C:\CURRENT.BAT ECHO. | DATE | FIND "Current" > C:\GDATE.BAT CALL C:\GDATE.BAT < C:\CURRENT.BAT DEL C:\CURRENT.BAT > NUL DEL C:\GDATE.BAT > NUL the mo-da-year will be in TODAY. echo.|date>!!temp.bat echo set today=%%4>current.bat call temp.bat del temp.bat del current.bat rem>%TODAY%.T$T NOTE! Following lines beginning with "for" should be all on one line. Also note that the line beginning with "for %%y" handles years 1993 through 1999 only. You will need to change this on January 1, 2000. for %%m in (01 02 03 04 05 06 07 08 09 10 11 12) do if exist %%m-??-19.T$T set M=%%M for %%d in (01 02 03 04 05 06 07 08 09 10) do if exist %M%-%%d-19.T$T set D=%%d for %%d in (11 12 13 14 15 16 17 18 19 20) do if exist %M%-%%d-19.T$T set D=%%d for %%d in (21 22 23 24 25 26 27 28 29 30 31) do if exist %M%-%%d-19.T$T set D=%%d for %%y in (3 4 5 6 7 8 9) do if "%TODAY%" == "%M%-%D%-199%%y" set Y=%%y del %TODAY%.T$T SET TODAY= SET M= SET D= SET Y= @ECHO off ::set month to alpha as an environment variable using plain dos ECHO.|date>gdate.bat ECHO set today=%%4 > current.bat CALL gdate.bat DEL gdate.bat DEL current.bat REM>%TODAY% FOR %%m IN (01 02 03 04 05 06 07 08 09 10 11 12) DO IF EXIST %%m-??-?? SET MN=%m IF "%MN%" == "01" set MON=Jan IF "%MN%" == "02" set MON=Feb IF "%MN%" == "03" set MON=Mar IF "%MN%" == "04" set MON=Apr IF "%MN%" == "05" set MON=May IF "%MN%" == "06" set MON=Jun IF "%MN%" == "07" set MON=Jul IF "%MN%" == "08" set MON=Aug IF "%MN%" == "09" set MON=Sep IF "%MN%" == "10" set MON=Oct IF "%MN%" == "11" set MON=Nov IF "%MN%" == "12" set MON=Dec IF exist %MN%-??-?? DEL %MN%-??-?? set TODAY= set MN= @echo off rem GETDTVAR.BAT rem Put current day, date, time into every LOGDAY, LOGDATE and LOGTIME ver | date > %temp%\gd.bat echo set logday=%%3 >current.bat echo set logdate=%%4 >>current.bat call %temp%\gd ver | time>%temp%\gd.bat echo set logtime=%%3 >current.bat call %temp%\gd for %%a in (%temp%\gd.bat current.bat) do del %%a>nul Get (GET26A.ZIP) is great for just this kind of thing. A shareware utility that does all kinds of things involving the environment. I need a way to (1) save the current DATE and (2) set the DATE ahead by a fixed number of days. Saving is easy, there'll be an ECHO . | DATE > in there somewhere. The second is trickier. I know that DATE will deliver a text string that will call CURRENT.BAT, which thus gets the MM DD and YYYY of today's system date. I believe too that if I can increment those values (wrap-around at end-of-month and end-of-year would be nice!) I can reset the date using the new values. How to increment string values? I've toyed with the idea of building a value by repeated copying of a 1-byte file: COPY ERASE1+1BYTE ERASE1 and then grabbing the size field of the DIR command output. I've toyed with the idea of setting a string to be the appropriate length (here's a 5-character string that represents today's date, here's a 14-character string that represents two weeks into the future, calculate them. My suggestion is to write a computer program to do it, even in BASIC. It would be cleaner, faster, and easier too, and could utilize system resources for doing the wrap or even avoiding February problems in leap years, or whatever. This won't be an answer to the problem as much as it is a theory that may apply. You may find it easier to manipulate the dates within the Julian Calendar, and when you've done all your calculations and so forth, then translate the Julian Calendar back to our normal calendar, and voila. REM BUMPDAY.BAT :: Increment the DAY by 1. Roll into next month. :: Calls SETMAXDY, BUMPMTH (and hence BUMPYEAR) @echo off call SETMAXDY set MAXMTH=12 if "1"=="31" goto BUMPMTH set RES=1 call INCBY1 set DAY=2 goto EXIT :BUMPMTH call BUMPMTH :EXIT @echo 8/2/1 REM end of BUMPDAY.BAT ======================================================================= REM SETMAXDY.BAT :: Define MAXDAY based on MONTH number :: Called from BUMPDAY.BAT @echo off if "%month%"=="1" set maxday=31 if "%month%"=="2" set maxday=28 if "%month%"=="3" set maxday=31 if "%month%"=="4" set maxday=30 if "%month%"=="5" set maxday=31 if "%month%"=="6" set maxday=30 if "%month%"=="7" set maxday=31 if "%month%"=="8" set maxday=31 if "%month%"=="9" set maxday=30 if "%month%"=="10" set maxday=31 if "%month%"=="11" set maxday=30 if "%month%"=="12" set maxday=31 REM end of SETMAXDY.BAT ================================================================== REM BUMPMTH.BAT :: Bump the MONTH number up by 1. Roll into the next YEAR. :: Called from BUMPDAY. Calls BUMPYEAR set DAY=1 if "2"=="12" goto BUMPYEAR :BUMPMONTH set RES=2 call INCBY1 set MONTH=2 goto EXIT :BUMPYEAR call BUMPYEAR :EXIT REM End of BUMPMONTH.BAT ======================================================================= REM BUMPYEAR.BAT :: Increment the year by 1. Called from BUMPMTH.BAT set MONTH=1 set RES=8 call INCBY1 set YEAR=2 REM end of BUMPYEAR.BAT ======================================================================= REM INCBY1.BAT :: Increment the environment variable RES by 1 :: called from BUMPDAY. BUMPMTH, BUMPYEAR @echo off if "%res%"=="30" goto 31 if "%res%"=="29" goto 30 if "%res%"=="28" goto 29 if "%res%"=="27" goto 28 if "%res%"=="26" goto 27 if "%res%"=="25" goto 26 if "%res%"=="24" goto 25 if "%res%"=="23" goto 24 if "%res%"=="22" goto 23 if "%res%"=="21" goto 22 if "%res%"=="20" goto 21 if "%res%"=="19" goto 20 if "%res%"=="18" goto 19 if "%res%"=="17" goto 18 if "%res%"=="16" goto 17 if "%res%"=="15" goto 16 if "%res%"=="14" goto 15 if "%res%"=="13" goto 14 if "%res%"=="12" goto 13 if "%res%"=="11" goto 12 if "%res%"=="10" goto 11 if "%res%"=="9" goto 10 if "%res%"=="8" goto 9 set YEAR=8 set DAY=1 set MONTH=2 call BUMPDAY (repeatedly) ======================================================================= REM BUMPDAY.BAT :: Increment the DAY by 1. Roll into next month. :: Calls SETMAXDY, BUMPMTH (and hence BUMPYEAR) @echo off call SETMAXDY set MAXMTH=12 if "1"=="31" goto BUMPMTH set RES=1 call INCBY1 set DAY=2 goto EXIT :BUMPMTH call BUMPMTH :EXIT @echo 8/2/1 REM end of BUMPDAY.BAT ======================================================================= REM SETMAXDY.BAT :: Define MAXDAY based on MONTH number :: Called from BUMPDAY.BAT @echo off if "%month%"=="1" set maxday=31 if "%month%"=="2" set maxday=28 if "%month%"=="3" set maxday=31 if "%month%"=="4" set maxday=30 if "%month%"=="5" set maxday=31 if "%month%"=="6" set maxday=30 if "%month%"=="7" set maxday=31 if "%month%"=="8" set maxday=31 if "%month%"=="9" set maxday=30 if "%month%"=="10" set maxday=31 if "%month%"=="11" set maxday=30 if "%month%"=="12" set maxday=31 REM end of SETMAXDY.BAT ================================================================== REM BUMPMTH.BAT :: Bump the MONTH number up by 1. Roll into the next YEAR. :: Called from BUMPDAY. Calls BUMPYEAR set DAY=1 if "2"=="12" goto BUMPYEAR :BUMPMONTH set RES=2 call INCBY1 set MONTH=2 goto EXIT :BUMPYEAR call BUMPYEAR :EXIT REM End of BUMPMONTH.BAT ======================================================================= REM BUMPYEAR.BAT :: Increment the year by 1. Called from BUMPMTH.BAT set MONTH=1 set RES=8 call INCBY1 set YEAR=2 REM end of BUMPYEAR.BAT ======================================================================= REM INCBY1.BAT :: Increment the environment variable RES by 1 :: called from BUMPDAY. BUMPMTH, BUMPYEAR @echo off if "%res%"=="30" goto 31 if "%res%"=="29" goto 30 if "%res%"=="28" goto 29 if "%res%"=="27" goto 28 if "%res%"=="26" goto 27 if "%res%"=="25" goto 26 if "%res%"=="24" goto 25 if "%res%"=="23" goto 24 if "%res%"=="22" goto 23 if "%res%"=="21" goto 22 if "%res%"=="20" goto 21 if "%res%"=="19" goto 20 if "%res%"=="18" goto 19 if "%res%"=="17" goto 18 if "%res%"=="16" goto 17 if "%res%"=="15" goto 16 if "%res%"=="14" goto 15 if "%res%"=="13" goto 14 if "%res%"=="12" goto 13 if "%res%"=="11" goto 12 if "%res%"=="10" goto 11 if "%res%"=="9" goto 10 if "%res%"=="8" goto 9 if "%res%"=="7" goto 8 if "%res%"=="6" goto 7 if "%res%"=="5" goto 6 if "%res%"=="4" goto 5 if "%res%"=="3" goto 4 if "%res%"=="2" goto 3 if "%res%"=="1" goto 2 if "%res%"=="0" goto 1 pause goto exit :31 set res=31 goto exit :30 set res=30 goto exit :29 set res=29 goto exit :28 set res=28 goto exit :27 set res=27 goto exit :26 set res=26 goto exit :25 set res=25 goto exit :24 set res=24 goto exit :23 set res=23 goto exit :22 set res=22 goto exit :21 set res=21 goto exit :20 set res=20 goto exit :19 set res=19 goto exit :18 set res=18 goto exit :17 set res=17 goto exit :16 set res=16 goto exit :15 set res=15 goto exit :14 set res=14 goto exit :13 set res=13 goto exit :12 set res=12 goto exit :11 set res=11 goto exit :10 set res=10 goto exit :9 set res=9 goto exit :8 set res=8 goto exit :7 set res=7 goto exit :6 set res=6 goto exit :5 set res=5 goto exit :4 set res=4 goto exit :3 set res=3 goto exit :2 set res=2 goto exit :1 set res=1 goto exit :0 set res=0 goto exit :1 set res=1 goto exit :exit REM end of IncBy1.BAT ================================================================== Run this through DEBUG, like so: DEBUG < SPFOWARD.SCR. n spfoward.com a 100 mov ah,2c int 21 inc ch mov ah,2d int 21 ret (blank line) rcx b w q Then, anytime *before* 11PM on any day (because it doesn't check to see if the hours are > 11PM and won't adjust the day right if so), just do SPFOWARD from DOS. When fall comes, make a copy of SPFOWARD.SCR called FALLBACK.SCR, change the N at the top to read N fallback.com, change the "inc ch" to "dec ch", and run the fallback.scr through DEBUG, run FALLBACK from DOS *after* 1am on any day and you'll be back to non-DST time. Hope this helps. Chapter 13: Extracting text strings =================================== The other day I received a letter on my bulletin board. The writer wanted to know if there was a method to extract parts of a text string and use it in a batch file. I write this message to ask if either of you know a way to extract portions of a text string using batch commands. If available, I could eliminate use of the GWBASIC program referred to above, making the program all-batch. Can't help with extracting strings within a batch program except by using some external program as you have done. But if you are only interested in parsing the date, the following is an extract of a batch program I saved from this conference that does that. echo.|date>!!temp.bat echo set today=%%4>current.bat call temp.bat del temp.bat del current.bat rem>%TODAY%.T$T NOTE! Following lines beginning with "for" should be all on one line. They just wouldn't fit that way in my editor. Also note that the line beginning with "for %%y" handles years 1993 through 1999 only. You will need to change this on January 1, 2000 . for %%m in (01 02 03 04 05 06 07 08 09 10 11 12) do if exist %%m-??-19.T$T set M=%%M for %%d in (01 02 03 04 05 06 07 08 09 10) do if exist %M%-%%d-19.T$T set D=%%d for %%d in (11 12 13 14 15 16 17 18 19 20) do if exist %M%-%%d-19.T$T set D=%%d for %%d in (21 22 23 24 25 26 27 28 29 30 31) do if exist %M%-%%d-19.T$T set D=%%d for %%y in (3 4 5 6 7 8 9) do if "%TODAY%" == "%M%-%D%-199%%y" set Y=%%y del %TODAY%.T$T SET TODAY= SET M= SET D= SET Y= The code we're discussing looks like part of a date-formatting program. I wrote such a batch program, setting DAY to Tue (or whatever), and DATE to 05-29-1926 (or whatever), but I couldn't figure out how to extract the components of DATE (ie. separate 05 from 29 from 1926) with batch commands. So, my batch program calls a GWBASIC program which does the extraction and conversion of month from numeral to month-name, and sets the month-name. This lets me place in my opening menu such gems as Tuesday the 8th of May 1926. The basic program is fine, assuming every machine you run this on has gwbasic. if you want to keep everything DOS-ish, the way I described is the way to go. I'll try to explain it better: echo @echo off > current.bat echo @set day=%%3 >> current.bat echo @set date=%%4 >> current.bat echo. | date | find "Current" > gdate.bat call gdate.bat < current.bat Here goes: The first three lines simply create another batch file. It's contents are: @echo off @set day=%3 @set date=%4 This batch file sets a var "day" and a var "date" based on parameters passed to it, the 3rd and 4th specifically. The 4th line of the first batch file creates a file containing one line. Here's the contents of gdate.bat: Current date is Tue 02-12-93 Finally, the last line runs the batch file created, using the contents of the 2nd file as -input- ... the %3 and %4 pick up "Tue" and "02-12-93" respectively. It's a way of getting around an inefficiency in DOS. From my point of view, using a program is fine, too. That's what PC's are for. TODAY.BAT ========= for %%m in (01 02 03 04 05 06 07 08 09 10 11 12) do IF exist %%m-??-19.T$T set M=%%M for %%d in (01 02 03 04 05 06 07 08 09 10) do IF exist %M%-%%d-19.T$T set D=%%d for %%d in (11 12 13 14 15 16 17 18 19 20) do IF exist %M%-%%d-19.T$T set D=%%d for %%d in (21 22 23 24 25 26 27 28 29 30 31) do IF exist %M%-%%d-19.T$T set D=%%d for %%y in (3 4 5 6 7 8 9) do IF "%TODAY%" == "%M%-%D%-199%%y" set Y=%%y del %TODAY%.T$T SET TODAY= SET M= SET D= SET Y= Chapter 14: Different batch enhancers and using scan codes ========================================================== This book will describe different utilities, batch enhancers, shareware, public domain and the use of scan codes that increase the flexibility and functionality of batch files further. Sharewares are like the book you are just reading: You find these programs on bulletin boards and internet all over the world and download them to your own computer. Normally you can evaluate the shareware for a certain time. Do you find the product useful and will continue using it, you have to pay for it. This is also what you have to do with the first program I will discuss later in this book, GET.EXE Chapter 15: Batch files and mail ================================ I often visit different databases, bulletin boards and internet to collect and get information. The information is automatically loaded into my computer. The mail is read in my off-line mailreader. I want it to fetch my off-line mail packets from my download directory, place them in a mail directory and start my mail reader. Now, here's the tricky part. I'd like it to rename, rather than overwrite any existing packets, and I need it to be able to deal with packets from several BBSs at the same time. This is a batch file I've been working on. It seems to work okay when dealing with mail from one BBS only. I don't know enough about how DOS handles these commands when dealing with multiple files to even guess what might happen when there are several QWK packets involved. I wonder if it might be better to rename the packets before reading them. For general use, an on-screen message warning of impending deletions might be better. The beeps and .QQQ file extension meet my needs. MAIL.BAT ======== @ECHO OFF CLS rem if no new mail, just read old mail IF NOT EXIST C:\ZDOWN\*.QWK GOTO READ rem rem fetch packets from d/l directory MOVE C:\ZDOWN\*.QWK C:\ZMAIL > NUL rem warn if old packets will be deleted after this session IF NOT EXIST C:\ZMAIL\*.QQQ GOTO READ rem beep.com, beeps speaker BEEP BEEP :READ rem rem start mail reader C:\SLMR\SLMR.EXE rem if there was no new mail we are finished IF NOT EXIST C:\ZMAIL\*.QWK GOTO END rem delete oldest packets ECHO Y | DEL C:\ZMAIL\*.QQQ > NUL rem renumber packets :QW3 IF NOT EXIST C:\ZMAIL\*.QW3 GOTO QW2 REN *.QW3 *.QQQ > NUL :QW2 IF NOT EXIST C:\ZMAIL\*.QW2 GOTO QW1 REN *.QW2 *.QW3 > NUL :QW1 IF NOT EXIST C:\ZMAIL\*.QW1 GOTO QWK REN *.QW1 *.QW2 > NUL :QWK IF NOT EXIST C:\ZMAIL\*.QWK GOTO END REN *.QWK *.QW1 > NUL :END rem goodbye! CLS Chapter 16: How to suppress the writing on the screen? ====================================================== I keep most of my programs zipped in a directory called zips and use this batch file to run them: @echo off md \temp cd \temp pkunzip c:\zips\anyname.zip anyname.exe pkzip /u c:\zips\anyname.zip cd \ deltree /y c:\temp This works just fine, but I would like to suppress the writing on the screen of pkzip as it un-compresses I believe it involves using >@ after the line " pkunzip c:\zips\anyname.zip >@ and this seems to work except that the @ keeps getting updated when I close the program. What I want is to "> nul" to prevent screen writing while unzipping. @echo off md \temp cd \temp pkunzip c:\zips\anyname.zip > nul anyname.exe pkzip /u c:\zips\anyname.zip cd \ deltree /y c:\temp The redirection command is > nul not >@. The only thought about how to improve your batch file would be to use a command line variable for the name of the zip file (anyname). If your batch file, for example, is named dozip.bat, then you could call it with dozip anyname and substitute the variable %1 where ever anyname appears in your batch file. This would make the batch file general purpose for any zip filename. Chapter 17: How to have a batch file testing if Windows is running ================================================================== EXITING WINDOWS? What is the best "Exit Windows" command? Not sure if this is a help but there's a 8192 byte exe file called Winexit.exe you could use as a quick exit from Windows. If put in windows as an icon, you would double click it and you are back to dos. If you are trying to automate a windows, have you tried the key-stroke recorder in windows? Have you heard or tried Winrun.exe? Its a program that lets you start a windows program from the command line or a batch file. I have one that goes right to Winfax. If you are interested in Winexit.exe and can't find it let me know and I'll send it to you as a debug script. I use WinBatch from WilsonWindowWare to do this kind of thing. It allows you to do just about anything you need and you can use the included compiler to create .EXE files. I love this thing... ...and it's cheap. 1. I've found that Winclock does not allow me to run winexit.exe as an alarm (although it can run all other programs as WP, Excel, Becker tools Backup and many more. It even allows you to write lines to these programs when starting them. 2. I've got the DOS-version of my fax program, so I can simply run my fax as an TSR and then make a batch-file calling the BBSs. It's quite a tool. I used it last week to run a PC maintenance program on 100+ PCs notion wide. It contains most of the needed logical expressions of a full programming language, with the simple syntax of dos. I tend to use it for the windows functions of my batch files, where my batch file calls windows after replacing Startup.grp with a new one including my winbatch .EXE. It is kind of shareware, but you need to buy the full boat to get the compiler(well worth it!) How to have a batch file test to see if Windows is running. You know about using EXIT, but this program needs to be executed from another shell that also employs the exit command. Further, you need to echo a message to the user if Windows is running. Well, you would take windows out of the path statement, or move it to the end of the statement, and insure that the following is in a path that occurs before the windows...... @echo off cls prompt Type EXIT to return to Windows!$_$P$G C:\WINDOWS\WIN %1 %2 prompt $P$G cls You can test if the variable windir exists: if '%windir%==' echo Not in Windows! if not '%windir%==' echo Windows running! @echo off cls prompt Type EXIT to return to Windows!$_$P$G C:\WINDOWS\WIN %1 %2 prompt $P$G cls Did you know you can do this with "set winpmt="? That will accomplish the same thing, except you don't need a batch file to load win. I use a simple utility called ISWIN (look for it on your favorite BBS). When run in the batch file it returns an errorlevel that you can test for and branch your batch file accordingly. Simple, easy to use.. If you don't mind using a third party program, try out this little number that I just whipped together for you: --- CUT --- n iswin.com e 0100 B8 80 46 CD 2F 3D 00 00 75 05 B0 01 EB 15 90 B8 00 16 CD 2F e 0114 3C 00 74 09 3C 80 74 05 B0 01 EB 03 90 B0 00 B4 4C CD 21 rcx 0027 w q --- CUT --- Save the text between those two '--- CUT ---' lines to a file called ISWIN.ASC and compile it to a .COM file like so: DEBUG < ISWIN.ASC. This will create the file ISWIN.COM which you then include in your batch file. This file will set ERRORLEVEL to 1 if windows is running, or 0 if not. Here's a demo: --- CUT --- :* Example batch file to demo ISWIN.COM @ECHO OFF ISWIN IF NOT ERRORLEVEL 1 GOTO NoWin ECHO Windows is currently running. GOTO EndIt :NoWin ECHO Windows is *NOT* running. :Endit --- CUT --- Interestingly enough, one of the windows magazines I read, had a batch file for this sort of thing, that set a environmental variable of something like set W=Y, and the batch file looked for this variable if you were shelled out of Windows to Dos, and tried to enter dos by typing WIN again. Wonder why they just didn't have the batch file search for the WINDIR variable. One other way would be to pipe the output of MEM/C to FIND WIN. Again, try before you rely. I assume that you mean to test for the presence of MS Windows being "loaded" as apposed to a program running. For that purpose there is the environmental variable "windir" which identifies which directory the MS Windows program resides. It only exists when MS Windows has been loaded. You would test for it as follows: if "%windir%"=="C:\windows" [insert a command here] Note that the correct case is important. After loading MS Windows, you can type "SET" at the DOS prompt to find the correct directory and the exact case usage of "windir". Exactly what were you referring to about knowing about EXIT usage? Were you eluding to the fact that when your attempt to exit MS Windows, open DOS programs are check for and identified as running, inhibiting the closure of MS Windows. I see I was a bit vague there. Let me better explain. First, something you already know (for those that may not). When you place something like %EVAR% into a batch file, DOS replaces all occurrences of %EVAR% with the contents of the respective named environment variable. So, if you have something like 'HOMEDIR=C:\FINN' in your environment, then the batch file command 'CD %HOMEDIR%' is translated to 'CD C:\FINN'. If DOS cannot find an environmental variable of that name, then it simply replaces it with nothing. (eg, if HOMEDIR was not defined, then 'CD %HOMEDIR%' would just become 'CD '.) Now, for the new stuff (maybe!). DOS is CASE SENSITIVE when it compares things (like environment variables, filenames, etc). AND it turns everything it processes from command lines and batch files into UPPER CASE (other that ECHO's and the like). Therefore, the line in your batch file: IF '%windir%==' echo Not in windows! becomes IF '%WINDIR%==' ECHO Not in windows! Notice how the WINDIR environment variable *NAME* (not contents!) has been converted to UPPER CASE there? Now DOS searches for the occurrence of *UPPER CASE* environment variable called WINDIR. Do a SET from a DOS window and look at your environment variables. The 'windir' variable is in lower case. DOS, though, is looking for it in UPPER CASE. In DOS, upper case 'WINDIR' is not the same as lower case 'windir' (remember, COMMAND.COM is CASE sensitive!), so it replaces %WINDIR% with nothing. As a result your line is translated to: IF '==' ECHO Not in windows! every time! Questions? When you have registered your Run Batch Run Book you may get support for your batch problems by sending email to the address below. *** Finn Roaas, Oslo, Norway, internet: froaas@online.no *** Now, another method that comes to mind is to pipe a SET command to FIND end search for "windir": SET | FIND "windir" > temp.fil Next, one could use COPY to determine if the file is zero length. Another way would be to pipe the output to a batch file, CALL that file, then run the test as before (DOS will have set WINDIR from the temporary batch file). And, as I mentioned in another message, one could search the output of MEM/C. if '%windir%==' echo Not in Windows! if not '%windir%==' echo Windows running! Unless you are running NDOS/4DOS, this won't work, though. If you are using NDOS/4DOS, be aware that you will be taking chances if you need to run it on other machines! Also, take a look at the little ISWIN.COM which will do the job nicely. Chapter 18: Invisible cursor ============================ Is there an ANSI.SYS prompt to make the cursor invisible? If you do not mind the cursor blinking just set the prompt to prompt $H. This is the 'backspace' command for the prompt, so it overwrites the C> default. If you DO mind the blinking cursor you can use ansi to color the foreground and background the same as your normal background color. Chapter 19: Numbered repeats in batch files ============================================ I have the following batch file to print labels... LABEL.BAT ========= :LOOP COPY D.TXT lpt1 GOTO LOOP and the file 'D." is D.TXT ===== Finn Roaas Ole Reistads vei 39 N-1068 Oslo NORWAY Now, the batch file works perfectly, but with my printer having a buffer, I'm not sure how many labels I'm gonna get. If I don't press CTRL-BRK, I'll blow up the printer or it'll go till we're all dead. How do I get the batch file above to ask for a number to print, then print that many and quit? There are a couple of ways: 1. I can get a shareware program called GET which does arithmetic within a batch. 2. I can try modifying and incorporating the following batch files: CHANGEJ.BAT =========== Rem changej.bat @echo off REM Calling is done via: REM CALL CHANGEJ 0 U (increase) REM CALL CHANGEJ 9 U (decrease) REM Variables H, T, U must be REM initialized to single digits. set X=%2 if %X%==U set O=%U% if %X%==T set O=%T% if %X%==H set O=%H% set S=P if %1==9 set S=M goto %S%%O% :P0 :M2 set V=1 goto Y :P1 :M3 set V=2 goto Y :P2 :M4 set V=3 goto Y :P3 :M5 set V=4 goto Y :P4 :M6 set V=5 goto Y :P5 :M7 set V=6 goto Y :P6 :M8 set V=7 goto Y :P7 :M9 set V=8 goto Y :P8 :M0 set V=9 goto Y :P9 :M1 set V=0 :Y set %X%=%V% if "%X%"=="U" if %U%==%1 CALL changej %1 T if "%X%"=="T" if %T%==%1 CALL changej %1 H set J=%H%%T%%U% for %%v in (N O S X) DO set %%v= CNT.BAT ======= REM Cnt.bat @echo off REM CNT.bat to demonstrate REM CHANGEJ.bat REM ========================= for %%v in (U T H) DO set %%v=0 cls echo This routine counts from 1 to echo 12 and then backwards from 12 echo to 1. This is achieved using echo DOS statements only. It sets echo a variable J which may be used echo for stack-handling. The range echo of J is 000 through 999, but can echo be enlarged easily. echo. echo Hit any key to go on ... pause >nul cls :INCR CALL changej 0 U echo %J% if not %J%==012 goto INCR :DECR CALL changej 9 U echo %J% if not %J%==001 goto DECR :Z for %%v in (U T H J) DO set %%v= Neither of the above .bat files are mine. I picked them up some time ago and unfortunately did not record the name of the author. If you want plain dos and you don't want too many copies, or you are prepared to execute the batch file several times, this would do the job quick and dirty. Place the number of arguments on the line (any character will do) for each time you want it executed. Put 20 on the line, execute it, do an f3 to recopy the line, and you got 40 labels. Not pretty, but if you want something quick, that will do it. X.BAT ===== @echo off :loop COPY D.TXT lpt1 GOTO LOOP shift if not '%1'=='' goto loop Try this file I wrote called COUNT.BAT. It avoids having to use any disk access and can easily be expanded out to whatever number of digits you need to use. Simply pass the number of times to loop as a command line variable. COUNT.BAT ========= @echo off Rem Use this file as a basis for counting functions Rem COUNT.BAT accepts variable %1 as the number of times to loop Rem Initialize Place Holder Variables set d1=0 set d2=0 set d3=0 Rem Start the incrementing process :incr if %count% == %1 goto incr_exit if %d1%%d2% == 00 goto 1digit if %d1% == 0 goto 2digit set count=%d1%%d2%%d3% goto do :1digit set count=%d3% goto do :2digit set count=%d2%%d3% goto do Rem Functions,programs, etc. to be looped %1 number of times :do echo %count% Rem Increment the 1s digit. When it reaches ten, move on the 10s increment :incr_1 if %d3% == 9 goto incr_10 if %d3% == 8 set d3=9 if %d3% == 7 set d3=8 if %d3% == 6 set d3=7 if %d3% == 5 set d3=6 if %d3% == 4 set d3=5 if %d3% == 3 set d3=4 if %d3% == 2 set d3=3 if %d3% == 1 set d3=2 if %d3% == 0 set d3=1 goto incr Rem Reset 1s digit. Increment the 10s digit. When it reaches 100, move on Rem to 100s increment :incr_10 set d3=0 if %d2% == 9 goto incr_100 if %d2% == 8 set d2=9 if %d2% == 7 set d2=8 if %d2% == 6 set d2=7 if %d2% == 5 set d2=6 if %d2% == 4 set d2=5 if %d2% == 3 set d2=4 if %d2% == 2 set d2=3 if %d2% == 1 set d2=2 if %d2% == 0 set d2=1 goto incr Rem Reset 10s digit. Increment the 100s digit. When it reaches 1000, let Rem the user know the counter is beyond capacity :incr_100 set d2=0 if %d1% == 9 goto :incr_outofrange if %d1% == 8 set d1=9 if %d1% == 7 set d1=8 if %d1% == 6 set d1=7 if %d1% == 5 set d1=6 if %d1% == 4 set d1=5 if %d1% == 3 set d1=4 if %d1% == 2 set d1=3 if %d1% == 1 set d1=2 if %d1% == 0 set d1=1 goto incr Rem Let user know the file has looped beyond it's capacity :incr_outofrange echo Count has gone beyond 999! beep Rem Continue normal batch execution at this point :incr_exit Chapter 20: How you can write batch files that will execute certain commands based on the time of day? =========================================================== EXAMPLE .....some kind of "IF, ELSE" condition such as if the time of day is 3pm then xxx will be executed. I found the following debug script which creates a 10 byte executable called HOUR.COM. When you run HOUR.COM it returns an errorlevel that is the hour number in the 24 hour clock (11pm=23, etc.). You can then use the errorlevel to control your batch file. Extract the following between, but not including the lines to an ASCII editor and save as HOUR.SCR in the directory in which you want the HOUR.COM program to exist. Then at the command line for that directory run debug < hour.scr to create the hour.com file. HOUR.SCR ======== N HOUR.COM E 0100 B4 2C CD 21 88 E8 B4 4C CD 21 RCX 000A W Q Look at the documentation for the GET H command in Bob Stephan's BATch enhancer, GET.EXE. Look for GET25.ZIP on a BBS near you. There are third-party utilities that return errorlevels based on the time of day. For example, Bob Stephan's GET can return an errorlevel and environment string based on the hour, minute or second: GETCURRE.BAT ============ rem Loop until 3:00 pm :Loop rem Get the current hour get h 16 if not errorlevel 15 goto Loop rem This will execute at or shortly after 3:00pm (more or less) :MinLoop get h 32 if not errorlevel 15 goto MinLoop rem This will execute at 3:15pm +/- a second or so You could toss together a "poor man's" version of the H subcommand of GET by using the following DEBUG script, which produces a small COM file (473 bytes) built around the DOS Int 21/2Ch function: GETTIME.SCR =========== E165"GETTIME.COM" 0 E200"dTJ.BcEJn3qNZd165J2JIZIH3/mK6lLHwBJLU.06rVKNmJK18Y.GUo16GJ4Rp" E23D"7bPn/mMp7bQZt4RUUqPp756VB56Z7bQj75PZNLNg/06UU0AisWAnYG18YEHUo" E27A"16GJ4Rp7bPn/mMp7bQZt4RUoKOiJ5RZ/GMn/GNm7rPmlKNqJ4PUU0AisGBtYG" E2B7"18YkIUo16GJ4Rp7bPn/mMp7bQZt4RUALNXxaPY/GMn/GNm7rPmlKNqJ4PUU0A" E2F4"isGBtYG18E3OZ/0NZNKMpl4RUw4QoZqPi/GOn/0GioU08QIFIFJGBJ26q3X9k" E331".16L7LOoFLNi/GAm.mHXFrPWJaQU2HCtE16GxaMZ75RU6Y9UA2PV7rOUkXQj7" E36E"KNmFb9XlKMmh4Edt4NttmMjpaDBc.FjtKMoJ4NUErPU.LRWlKOX/0NjpKMdta" E3AB"9Bc.78IYQmxaQgJaRZl46q34PpJ46dB56YE99B50g6/cD.0..oJ.c00.7Tn1G" E3E8"pJ.Wcbi4.kHHpJ.W6bS2.knIpJUW4bC0.cv./USF..vzuGY.cr1.mECu2..hA" E425"pQ6HNZIEhf0.s9..c9..Qzw6GNn0MID..ERlHf.8G7n0s2U01HnVAcz.ILwMd" E462"ZLPBA.......3h7oQ6MBA" E100 B8 0 3C BA 65 1 33 C9 CD "!rC" BE 0 2 50 BD D9 1 55 BF 88 90 E117 "W3" DB B1 FA 8A F0 80 C1 6 32 E4 AC "<9v" 8 " nul). Good luck! Recently a friend of mine got a new dx2 at work and he installed some games and other useful programs. But his boss was a little pissed at a couple employees that seem to be more interested in playing than actually doing their jobs. He wanted my friend to restrict their access. What he would like to have was a batch file that, when it started to run a program, it first checked the time and if it was between 6am - 5pm would give a message that this program will not operate during business hours. He wanted to include a password that will allow access. I could put passwords in or just completely keep them out but that would be bogus. He would just like to let them know in an interesting way not to screw up a good thing. The simplest way I know of to do this is to create a small file called HOUR.COM (see the same file above) from the following debug script (this script was originally published by Brett Glass in InfoWorld several years ago). HOUR.SCR ======== N HOUR.COM E100 B4 2C CD 21 88 E8 B4 4C CD 21 RCX A W Q If you put HOUR.COM in a directory on your path then you can use it in your batch file. Hour sets an errorlevel to the current hour of the day (with 0 for midnight and 23 for 11 pm). You can then test the errorlevel in the next statements in your batch file, e.g. RUNATTM.BAT =========== hour if errorlevel 17 goto ok if errorlevel 6 goto nogood :ok goto end :nogood pause :end The errorlevel statements test for the argument or greater. If errorlevel 17 indicates that the time is between 5pm (17 hours in international time) and midnight, and will branch to the ok label and run the program. The next statement, if errorlevel 6 indicates that the time is 6am or greater, but that statement will not be executed if the previous statement has been executed. If the errorlevel 6 statement is executed, then the branch will be to the nogood label and your message will be displayed until another key is struck at which time the batch file will end and return to where it was called. If the hour is between 0 and 5 neither errorlevel statement will be executed and the command(s) in the ok label will be executed. Thus, all the hours you are interested in are covered in the two errorlevel statements. In this way a password is not necessary. Also, a knowledgeable user would still be able to run the program directly from a command prompt if he knew the command to run the program. Even if you added password protection into a batch file, the user would still have the same work around. PC's are not secure machines. Only baby-baby novices would be fooled by a batch file that wouldn't allow access to a program; nothing would prevent them from running it directly. Personally, I'd disallow games on a business machine. If you must, just leave the policing of the hours up to management. It's a simple matter of self-control on the part of an employee, one that can be discussed at his next evaluation if he can't stick to work during working hours. Let the employee know that's the deal. The time you spend disabling a program through a batch file will be wasted; it won't take long for anyone to see through it. Chapter 21: Return to directory =============================== Using just Dos, there is an easy way to have a batch file return you to the drive and subdirectory from which the batch file was started from. Try the following, naming it anything except director.bat or go.bat EXECUTE.BAT =========== @echo off echo @echo off> director.bat echo set olddir=%%2>> director.bat dir | find "Directory"> go.bat call go if exist