Batch File Programing

May 16, 2018 | Author: dhruvgupta90 | Category: Command Line Interface, Filename, Dos, String (Computer Science), Computer File
Share Embed Donate


Short Description

Download Batch File Programing...

Description

Living with DOS: (( Intermediate BATch Tutorial )) by

Barry Simon

Copyright (c) 1986, Capital PC User Group Inc. This material may be republished only for internal use by other not-for-profit user groups. Additional material copyright (c) 1986, Barry Simon Posted on Compuserve with permission of CPCUG. May not be reproduced without including the above copyright notice. Published in the November 1986 issue of the Capital PC Monitor.

Introduction One of the tools that most distinguishes the experienced DOS user from others is the effective use of BATch files. In this article, I will discuss some of the more advanced features of BATch files and their commands. I call this tutorial "intermediate" because I have tried to write in a manner accessible to those with only a little experience writing BATch files. Simple BATch files To begin with, a BATch file is a set of DOS commands which you place together and which you can issue by just typing the name of the batch file. The classic example is the batch file which changes to the directory containing Lotus' 123 and then runs 123. The same idea can be carried much further; for example, when I execute my word processor with a batch file, it o

loads the proper set of macros in by keyboard macro program;

o

makes a mark using Kokkennen's MARK/RELEASE package;

o

loads my thesaurus;

o

loads the appropriate mouse menu program;

o

runs the words processor; and

o after I am finished with the word processor, clears the macros and runs RELEASE to boot the thesaurus and mouse menu from memory. BATch files must be pure ASCII text files with separate commands

on distinct lines separated by carriage return/line feed pairs. To create your BATch files, you can use EDLIN, a text editor, or any word processor that produces straight ASCII text files. BATch programs can contain DOS commands, application program commands, or a variety of specialized programming features that are known as BATch commands. BATch Commands and Features Parameters Your editor may allow you to specify a text file to use as a parameter on the command line loading it. You would like to specify the file name as a parameter on the command line calling a BATch file to start your editor and have this file name passed on to the editor when it is loaded. This is quite easy. If your editor is called EDITOR.EXE and you load it via a BATch file called foo.bat, you need only make the line calling the editor say: editor %1 and then call up the BATch file as foo filename When the BATch processor comes to the %1, it looks for the first parameter following "foo" and replaces %1 by that parameter, in this case by filename. To be more precise, DOS parses the command line calling the BATch file into distinct "words" separated by one of four delimiters:

,

;

=

That is, it looks for strings of allowed characters separated by one or more of these special four. Any of the 256 ASCII characters are allowed in the strings except for these four delimiters, the three redirection characters (,|) and the ASCII nul. The first word on the command line is assigned the value %0, the next %1, etc. Normally, %0 is just the name of the BATch file but since "." is not a delimiter in parsing the line but is a delimiter in ending file names, if you have a BATch file foo.bat and type in foo.cpcugisgreat foo.bat will be run and %0 will have the full 17 character string assigned to it. Similarly, since DOS knows that file names are no more than 8 characters, the BATch file 12345678.bat will be run if you type in 12345678ABCDEFGHIJ but %0 will have an 18 character string. These are admittedly curiosities but DOS curiosities have a knack of being useful

sometimes. In a real sense, DOS assigns as many parameters as there are words on the command line, but initially you can only access the first ten as %0 through %9. Any place that %1 appears in the BATch file except as %%1, it will be replaced by the first word after the filename even if that word is the empty word. Any other time that the symbol % appears in the BATch file DOS will strip the %-sign away except that %% is replaced by a single percent and %%1 becomes %1 so if foo.bat has the single line: echo %%1 has the value %1 then typing foo junk will issue the message %1 has the value junk There is no limit on the size of any individual parameter other than the overall limitation that the entire DOS command line can contain no more than a total of 128 characters. To summarize, any time %i (for i=0,1,...,9) occurs in the file except as a %%i, it will be replaced by the ith string in the command line. The real limitation of BATch file parameters is that they are not variables. You cannot manipulate them by parsing them and cannot change their values. Labels As a preparation for discussing BATch file GOTO commands, I need to discuss labels. Any line beginning with the character ":" will be skipped by the BATch processor when it gets to it. This means that you can use such lines as remark lines which will not appear on the screen even if echo is on (in which case lines beginning with rem do appear). You can also place the redirection characters ,| on such a line (but you cannot place such characters on a "rem" line). And % signs are not treated specially on such lines. While DOS ignores such lines, the string following the : becomes a label for the GOTO command which I'll discuss next. The first word or the first eight characters of the first word become the name of that label. You can also place comments after a label name if you separate these comments with a space. GOTO The most significant way in which BATch files go beyond the DOS command line concerns two logical control structures, the GOTO and the IF commands. The line goto

will send the BATch file to the line immediately following the line on which the label appears. If the label appears more than once, its first appearance in the file is used. If the label does not appear, the processing of the BATch file is abruptly ended with the message "label not found". GOTO's can be used for either branching or some rather crude looping. Here is a simple example of branching. Suppose that you wish to send control codes to your printer easily from the DOS command line. You might prepare little files like ff.txt containing a formfeed (control-L), or boldon.txt with the codes for turning bold face on, etc. Then you could write a print.bat file which began: goto %1 :ff copy ff.txt prn goto end :boldon copy boldon.txt prn ETC with a label ":end" as the last line of the file. One problem with the limited logic allowed by BATch files is the difficulty of error checking. With the above, if you forget to put in a parameter or put in an illegal value, you would get the rather inelegant "label not found" message. Alternatively, you could replace the "goto %1" with separate lines such as: if %1 == ff, goto ff and then place an error message, hardly a neat solution. PAUSE The next BATch command that I'll discuss, PAUSE, unlike GOTO and parameters makes sense at the DOS command line. For straight DOS usage, this is pointless but for environments like CED or TallScreen which allow multiple commands on one line, it can be useful. What PAUSE does is display the message: Strike a key when ready . . . and pause the processing of the BATch file until a key is struck. Before the message is displayed, the keyboard buffer is flushed to prevent any stray keystrokes left over from previous operations from bypassing the effect of the PAUSE command. There are three rather distinct uses of the PAUSE command. The most well known is to allow the user to take an action like inserting a diskette into a drive. Often, you will want to echo a message to the screen before the PAUSE command such as: echo Place a diskette into drive B: and ... pause

A second use is to allow the user to see the output of some program before the BATch file continues. Without the PAUSE, the output might disappear too quickly to absorb. A third use that we'll see later is as an extremely crude device for user input. The IF command The second and last element of flow control provided by DOS is the IF command. Like pause, it also makes sense at the DOS command line. The syntax is IF (not) The not is an optional part which we'll explain later. is limited to three types: o

A test for the equality of two strings;

o

A test for the existence of a file; and

o

A test of the "error level".

Comparison

If the comparison is true, then the command in "consequence" will get carried out. If the word "not" is included, then is carried out only if the comparison fails. While consequence is typically a GOTO statement, any acceptable DOS or BATch command is allowed. You can even have the consequence be a second if statement as in if not %1 == ff if not %1 == boldon goto error As the last line shows, the syntax for checking strings is to use two equal signs. Strings are sequences of characters not including the standard delimiters (space, comma, semicolon or equal) or redirection signs. These redirection signs but not delimiters can appear if the string or part of the string is surrounded by single or double quotes. If an illegal string is used, DOS will reward you with "bad command or filename". There is a standard problem faced by users first exposed to BATch files. Often, you will want to test for an empty string, for example to give an error message if the user failed to provide a necessary parameter. Empty strings are not allowed so that the line if %1 ==

echo whoops

will yield "syntax error" if %1 is empty, and "bad command or filename" if %1 has the value "echo" unless of course you have a program named "whoops". The way out of this problem is to use the fact that %1 is replaced where ever it is and add a dummy parameter as in if a%1 == a echo whoops The possibility of looking for a file provides essential error checking. A common example of its use is to fix the deadly move BATch file:

copy %1 %2\%1 erase %1 This may seem like a great way of moving a file from one directory to another so that move foo.txt C:\junk will move foo.txt from the current directory to junk. But directory junk doesn't exist, the first line will give the message "Invalid directory" and the second line will erase file which has NOT been copied. Thus, as a protection one add before the "erase %1" line

if the error the should

if not exist %2\%1 goto end with an appropriate label and error message. There are many other places where such error checking can be invaluable. Unfortunately, "if exist" works with path names only in DOS 3.x and not in DOS 2.x. The final if comparison, "if errorlevel", is useless within the context of pure DOS commands since no DOS command (before DOS 3.2) sets errorlevel. But the DOS technical reference describes how a program can set this parameter and if you have a program that sets it, this comparison is useful. But I must warn you that the comparison if errorlevel 2 is TRUE not only if the value of errorlevel is 2 but if it is 2 or greater. Beginning with DOS 3.2, several external DOS commands such as BACKUP, RESTORE, and FORMAT set what the DOS manual calls "exit codes" which can be tested with "if errorlevel". Nested and Chained BATch files It is possible to make rather elaborate collections of BATch files which call one another. The simplest is the equivalent of a GOTO. If the name of another file appears as a line in one BATch file, the new BATch file will begin and you will NOT return to the first BATch file when the second one ends. Particularly since the BATch control structures (GOTO and IF) do not include CALL/RETURN processing of subroutines, one would like to be able to call a second BATch file as a subroutine and return to the first BATch file when the second one finished. Many books, especially the older ones, will tell you that this is not possible. However, in DOS 2.x and later, there is a method of doing precisely this kind of subroutine call. This is an example of something which is not undocumented but rather so badly documented that many experts did not realize its potential until some time had passed. The reason that an ordinary call to a second BATch file does not return you to the first is that command.com is only able to keep track of one BATch file. The

solution is to load a secondary copy of command.com to process the second BATch file. The correct syntax is command/c foo to call foo.bat from another BATch file. When foo ends, processing of the first BATch file will continue on the next line. Several warnings are in order concerning this command. As you may know, DOS has both internal commands like COPY and external commands like FORMAT. That is, once command.com is loaded during initial bootup, COPY becomes an available command while FORMAT is a stand alone program, which provided separately on the DOS disk, which must reside in the default directory or in the path to be available to the user. You might think that COMMAND was an internal command but it is external. That is, in order for a line like command/c foo to work, COMMAND.COM must be available in the default directory or in the path. In addition if you leave an old version of COMMAND.COM somewhere on your hard disk and that happens to be the one first found when this line is processed, you will get a message "incompatible DOS versions". Finally, there is a warning about the SET command discussed in the section below on global variables. FOR...IN...DO FOR...IN...DO is one of DOS' most powerful and least appreciated commands. It can be used at the DOS command line or in a BATch file with slightly different syntax. The syntax at the DOS command line is for %a in () do expression(%a) The use of a in %a is not important; you can use any letter or number or even extended ASCII code so long as it appears in all places. The % is important and since %'s get stripped from BATch files, the syntax in a BATch file must be "for %%a...". The keyword "do" must appear or you will get a "syntax error" message. Within the () can appear a list of ASCII strings separated by the standard delimiters. Following the keyword "do" can be any command with %a as a parameter which will be successively replaced by the values listed within (). For example for %a in (file1 file2 file3) do copy %a prn will issue three separate commands copying the three files to prn. The power of the FOR...IN...DO construction comes because you can include wildcards and DOS will substitute in turn each filename satisfying the wildcard, so for example, for %a in (file?) do copy %a prn

would do the same thing as the above command if there were no other files with the name file?. Therefore, the greatest use of FOR...IN...DO is to force programs which don't understand wild cards to understand them none-the-less! For example, when I discussed file viewers, I talked about both LIST and FILEVIEW. LIST allows you to give wildcard filenames so "list *.doc" would successively view all files with a doc extension. FILEVIEW does not have this built in but you can do it yourself: rename fv.exe [email protected] and make a one line BATch file called fv.bat saying for %%a in (%1) do fv@ %%a and suddenly FILEVIEW also has this capability. You can also force commands which don't treat wildcards "properly" to do so. For example, if you want to change the date/time stamp on a file foo.txt to the current date and time, the command copy/b foo.txt+,, will do precisely that. If one replaces "foo.txt" in the above command by *.*, DOS will create one file which is the combination of each file in the current directory, probably not what you intended. To change the date/time of all files use for %a in (*.*) do copy/b %a+,, You can combine multiple commands and wildcards as in for %a in (*.pas *.com) do copy %a A: If you want to stop such a command before it has run its course, Ctrl-C will give you the opportunity to break the loop. In addition you should be warned that a FOR...IN...DO loop is like a BATch file: if the expression called after the keyword "do" involves a BATch file, processing will not return to the FOR...IN...DO loop. It will only be processed one time even if you have several possibilities in your list. As happens for BATch files, placing command/c will prevent the chain breaking so for %a in (*.*) do command/c foo %a issued at the DOS command line would run the BATch file foo.bat successively with each file in the default directory as a parameter. The BATch processor is rather inefficient. It reads only one line of the file into memory at a time (try including a line like "erase foo.bat" in a BATch file to see what happens) although it keeps its place by counting the byte offset (try using your editor on foo.bat as a line in foo.bat to explore this). By using the FOR...IN...DO command to reduce the number of lines in a BATch file, you can speed up processing by a noticeable although not spectacular amount (perhaps by 10%). For example, if you have a large RAM disk and routinely copy several directories to it during bootup try (the "\*.*" isn't needed; I include it for emphasis). for %%a in (path1 path2) do copy %%a\*.* D: >nul

Two warnings about this procedure: you cannot include a command with its own parameters in the list since DOS processes the list in () one word at a time. Second, for technical reasons, I strongly recommend against loading resident programs in such a statement. SHIFT As I described above, when DOS parses the input command line to a BATch file, only the first 10 words are available as %0 to %9. However DOS keeps a record of the entire line. One of the things that the SHIFT command does is provide you with access to the other parameters. A line with the single command SHIFT drops %0 changes %1 to %0,..., %9 to %8 and makes what was the eleventh word on the original command line into the new %9. Additional calls to SHIFT repeat this process. If SHIFT were only good for accessing parameters beyond the initial ten, it would be of limited use. I cannot find any interesting use of this aspect of the command. Its real use lies in the possibility of having a real loop within a DOS BATch file. Here is a sample "touch.bat" expanding the one line procedure for updating the date/time stamp of a file: :top if %1x=x goto end for %%a in (%1) do copy %%a+,, shift goto top :end With this BATch file, you can issue the command touch followed by several parameters, each with wildcards. The basic operation is applied to each file meeting any of the filespecs listed as parameters. Of course one could probably do just as well with the single line for %%a in (%1 %2 %3 %4 %5) do copy %%a+,, While I can develop considerable enthusiasm for the FOR...IN...DO command, SHIFT does not evoke much excitement! ECHO Next, I turn to the issue of displaying information on the screen, the primary method of communication between the writer of a BATch file and the user. Even if you are writing BATch files for yourself, it pays to expend some effort in making attractive, instructive displays. By default, every line in the BATch file appears on the screen. While this has the potential advantage of showing the user what is going on, usually the display is so fast that it is more distracting than useful. You can turn off the automatic display of commands to the screen with the command echo off

When echo is off, you can display messages by preceding the desired communication with the keyword ECHO. The default for BATch file should be echo off and there are patches for COMMAND.COM to make that the default. I have avoided this patch because such a patch is not immediately available for new versions of DOS. Unless you make this patch, most of your BATch files should begin with echo off cls It is not necessary to turn echo on before exiting a BATch file; it is turned back on automatically. You can suppress the prompt on a DOS command line by typing "echo off" at the DOS prompt and then "echo on" is necessary to restore the default. ECHO can be a useful command. It's message is sent to standard output which means that you can redirect it and so use it to send codes to your printer. But be warned that a CR/LF pair is always appended to an echo line so echo ^L >prn (where ^L means control-L the form feed character) will not send only a form feed to your printer. It will send an extra line feed. Also, you will not be able to send escape codes to your screen or printer directly from the DOS command line. DOS reacts to your key by aborting the current command instead of placing an escape character at the cursor. With many editors you can put escape characters into a file and so write BATch files to send escape codes to the screen or printer. One character you may want to use is ^G (Control-G entered by depressing the control key and hitting g). This is the "BEL" character and will beep when sent to the screen. So echo ^GYou made an error will catch the user's attention. But please control yourself: avoid putting several ^G's together. And with most printers echo ^G >prn will beep the printer. A famous problem is how to use ECHO to make blank lines. A BATch file command line with the single word "echo" will not work as this will get the response "echo is on" or "echo is off". DOS 2.x had a celebrated undocumented feature: "echo" did produce a blank line but relying on this undocumented feature caused grief when DOS 3.x gave the "echo is on/off" response. Some versions of DOS have had echo . (note the period) produce blank lines but this has not always been true and has led to some rather fancy programs with installation

files showing bunches of dots on the screen. simple solution. To get a blank line try

There is a rather

echo where means including the character with ASCII code 255. You can't enter this in all editors but in many (e.g. EDLIN), you can by holding down the key and hitting 2 5 5 on the numeric keypad. Lest you be wary of using an undocumented feature of DOS, this trick merely relies on the documented feature of "echo" to send any character even those with codes above 128 to the screen: is a blank character. You can also use one of these characters to anchor down a message that you don't want to start in column one. Even if echo is off, the last line in the BATch file will appear on the screen if that line does not end in a carriage return /line feed pair. For this reason, you will probably want to be sure that the last lines in your BATch files have such a CR/LF pair at the end. The exception is if the last line is "cls". In this case the echo to the screen is unimportant and adding a CR/LF will sometimes place the prompt on line three instead of line two. Using ANSI.SYS If you are writing for a "mass market", you cannot assume that the user of your BATch files has ANSI.SYS installed but if you are writing for yourself or for a colleague, you can be sure it is installed. ANSI.SYS provides a simple way of controlling colors and, to get really attractive screens, the location of messages. You should consult your DOS manual (or the DOS technical reference for DOS 3.x) to learn how to move the cursor. For example, if you want to start with echo off and then only erase the line "echo off" without clearing the whole screen, try: echo off echo [A[K Input the Inelegant Way One of the weaknesses of the DOS BATch processor is its inability to accept input from the user. This is of importance not only when writing for others. You might want a BATch file to run a program and then ask if you wanted to make a backup. Of course, if you knew the answer to this backup question in advance you could write the BATch file to get such input as a parameter when the BATch file was loaded but there is no simple way to get input once the BATch file is running. The best way to overcome this lack is to use one of the programs I'll be discussing in later articles in this miniseries. Lacking that, I know of two methods to get user input just using DOS's tools. First, Control-Break (or Control-C) will stop a BATch file (or rather give you the message "Terminate Batch file(y/n)?") and so you can point out to the user the option that is always available any ways. For example, if backing up is all that is left you could put in the lines:

echo To prevent backup hit Control-Break; otherwise Pause Since you can accidentally brush a key, this is hardly an ideal solution. Also, you can end a BATch file by displaying a menu with choices labelled "a,b,c" and have BATch files called a.bat, b.bat, c.bat to run depending on the user's response. Global variables If one chains or nests BATch files, it is easy to pass parameters between them by putting the parameters in the command line calling the second BATch file. But what about BATch files called at different times. For example, you may have noticed that the a.bat,... procedure above seems to have the disadvantage that you can only use it for one menu unless you use different directories or different letter choices. Wouldn't it be better if there were a place to put "global variables" so you could set menuchoice=1 before displaying a menu and have a.bat do different things depending on the value of "menuchoice". Well, DOS has precisely such global variables although a part of the procedure is undocumented. When COMMAND.COM is initially loaded, it sets aside a region of memory as "the environment" which by default is 160 bytes. My article in last November's monitor lists patches to increase this size by patching command.com and DOS 3.1 and 3.2 have a mechanism of increasing environment size by a command in your config.sys file. This SHELL command option is documented in DOS 3.2 but undocumented (and slightly different syntax) in DOS 3.1. The environment is intended primarily to store the location of COMMAND.COM when its transient portion needs to be loaded, your path and prompt and information that the user can provide various programs. However, you can also use it to store global variables for communication between your BATch files. Placing information into the environment is a documented DOS command. You use SET. Thus SET name=string will define a global variable "name" to have the value "string". As usual, "name" doesn't distinguish between lower and upper case; if you look at the environment by typing "SET" with no parameters, the variable will appear as NAME=string Upper and lower case are distinguished in strings. that spaces count so that the command SET name = string

Notice also

will define another variable "NAME "(note the space). Getting the value of a global variable is easy from within a BATch file. If a name appears between percent signs, then DOS will replace the string %name% by its environmental value. Thus if you issued "set foo=fun" and later have a line like if %foo%=fun goto success then the BATch file will go to the label success. If foo has no current value, %foo% is replaced by the empty string. Several warnings are in order. First, this procedure is undocumented. However, it has been constant from DOS 2.0 through 3.2 and is so close to a documented procedure available to programs that it is as likely to remain in DOS as anything that is not documented. Second, while you can use the SET command to define variables whose names have spaces in them or whose name begins with a numeral, you cannot use %name% to access such variables. A final warning. If you use command/c to nest a BATch file, DOS makes a copy of the environment for the new shell that runs the nested BATch file. Anything in the original environment is in the new one so global variables are available to the new shell. However, any changes made in the environment by the nested BATch file via a SET command are only saved in the secondary environment and will be lost when you return to the original BATch file. What are global variables good for? I have placed today's date in English (that is January 1, 1980 rather than 1-1-80) in my environment at bootup and then I have a letter.bat which makes a copy of a template with my address and my word processor's formatting command and I append to this copy via echo (char 255)

%date% >>%1

Key Stacking Wouldn't you like to call up TURBO PASCAL in a BATch file which automatically answered Y to the opening question, hits W, supplies the name of a file that you passed to the BATch file as a parameter and then hit E for edit? Or wouldn't you like to have a key struck automatically in response to the IBM logo and "hit any key to continue" at the start of so many IBM programs? BATch files need a command that lets you prestack some convenient strokes in the keyboard buffer. However, there is one crude way of providing keyboard input with DOS tools if you can provide all the required input in advance. For example, if you want an "erase *.*" command in a BATch file and would like to avoid having to answer "Are you sure(Y/N)?", prepare a file, "yes.txt" with the single line "Y" (and including a CR/LF) and place the line erase *.* < yes.txt in the BATch file. Two warnings are in order here. Be sure you have a complete set of responses or else your system will hang.

In response to the "Are you sure", you must respond Y followed by so if you left the CR/LF out of yes.txt, "erase" would patiently wait for the and wouldn't take it from the keyboard since you told it to only take input from yes.txt. Second, you cannot redirect input and output to a BATch file as a whole but you can redirect input or output of individual commands if the commands use standard I/O. Thus, you cannot make a file, 2yes.txt, with two yes lines and a foo.bat with two lines saying "erase *.*" and use "foo
View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF