CALL
is much like calls in high level languages. It
causes the name of the calling batch file and the location in the file to be saved
(by COMMAND.COM) so that execution can be resumed at the next line in the file, when
the called batch file terminates. Since each CALL consumes some memory until it is
cleared by the return of the called program, there is a finite limit to the number
of CALLs that can be nested. I don't know what this limit is, or any other details
of how the call in managed internally by COMMAND.COM. You can demonstrate the
existence of the limit with this program
@echo off
call %0
:end
which will just sit there with the cursor blinking for quite a while before issuing
an error message and terminating (the following is a screen dump of the above).
H:\>test
Insufficient memory
H:\>
CALL lets you invoke a batch file from a batch file without loosing
your place in the first one. The two batch files may be different files, or the same file.
When they are the same, the effect is that of recursion. CALL causes COMMAND.COM to save the
name and file pointer for the current file before invoking the second one and to reenter the
original file at the location indicated by the file pointer on its termination. CALL can also be
used to invoke executables, though COMMAND.COM doesn't seem to do anything different when you do.
However, there is a certain flexibility in using CALL to invoke executables: you can later replace
the .EXE file with a same named .BAT file to change the action. It is also safer to use
CALL when you don't know for sure that the program you have been told just the name of is in
fact a .COM or .EXE, rather than . .BAT file. CALL also is useful in FOR
loops both in batch files and from the command line to prevent the loop from terminating
prematurely when the action is a batch file (FOR %a in (foo.bat bar.bat baz.bat) do %a will
execute only FOO, but FOR %a in (foo.bat bar.bat baz.bat) do call %a will execute
all three).
CD changes the default directory on either the default or given drive. It is important to keep in mind that when changing the directory on a non-default drive the default drive itself is not changed:
c:
cd d:\foo
leaves you in the C: drive, but changes the default directory on the D: drive
to \FOO. This is sometimes useful, but it should be kept in mind that under
Windows, the default directory on any drive is subject to being changed by
another program while the batch file is running - it is a very good idea to
assume nothing about the default directory though not all of the examples in
this book actually take that recommended precaution. Not even the default
directory on the default drive for the window in which the batch file is
running can be assumed to be stable.
When running under Windows it is seldom necessary to remember what the previous directory was when changing it, but under plain DOS it often is. There are several utilities available that push and pop directories - these utilities are well worth using, but since this book is about what can be done using just what comes with MSDOS 6.22 they are ignored here. For most purposes only the default directory on one drive needs to be saved and restored:
@echo off
dir
dir | find "Directory" > }{.bat
echo set dir=%%2> director.bat
call }{
del }{.bat
del director.bat
cd \
dir
cd %dir%
dir
:end
illustrates that - note that it assumes that the default directory is writable and stable. The usual way of handling unstable directories is by specifying the directory, but that doesn't work here because there isn't any reasonable way to include the directory in }{.BAT. The work around I use is to map a drive to a directory and do my DOS work there - the special drive must not be used for any Windows programs, though it is safe to let many Windows programs work with files there. It is especially important to do something like this if the working directory is on the same drive as Windows.
DIR generates a list of files and/or subdirectories in the
current or given directory. It has a number of switches that modify its action and
the output is frequently redirected into files, or through filters to modify the
output even more. The HELP on DIR is unusually through and accurate, and is
misleading hardly at all. Since I really can't say it any better than MS did, see
the HELP entry and/or the built in syntax information (the /? switch). DIR is
an internal command and has no errorlevel return. One extension to its functionality
that was omitted from the command but is highly useful is the ability to display
listings for multiple patterns in the same command:
doesn't work, but would certainly be handy for listing all the programs in a
directory. Needless to say, I have written a batch file that does this: DIRX.BAT.
dir *.exe *.com *.bat *.pif
Again, please see HELP DIR or DIR /? for the syntax (there just isn't much way to rewrite the material and I don't want to just copy existing material for this book. If you insist, a dump of the /? stuff is in a separate file here (I'll probably wind up doing that for most of the commands if MS doesn't get in my case about it). The file was generated with the command
dir /? > dirhlp.txt
ECHO (on, off, or text)
is really two commands: one to control
the ECHO status (whether the command lines in the file will be displayed, or just the messages
they generate) using the ON and OFF arguments, and one to display text on the console
(through STDOUT (STandarD OUTput)). The fact that the ECHO status has no effect on ECHOed
text points out that difference. Most batch files begin with @ECHO OFF to suppress display
off all the commands in the file (the '@' symbol suppresses echoing of the line it begins, so
not even the ECHO OFF command is displayed). If a batch file is always invoked or called
by another, only the first one need have the @ECHO OFF command, which will remain in force
as long as COMMAND.COM remains in batch mode. Note that this does not affect secondary
command processors:
@if "%1" == "" echo off
if "%1" == "" command /c%0 foo
:end
ECHO <text> seems to have been provided as a means of issuing messages to the user, but there are other uses. The not well documented syntax ECHO. (note the '.' at the end of the command) ECHOs a blank line. This is quite useful, when piped to certain commands, for supplying the <Enter> required to terminate the command:
@echo off
echo. | date
echo. | time
:end
ECHO is also used in a similar way with 'y' or 'n' to provide an automatic response to a command requiring a Y/N response. The most common use of this is, perhaps, to automatically delete the garbage in the TEMP directory during AUTOEXEC.BAT:
echo y | del c:\temp\*.*
But beware - always specify the exact drive and directory in full - never do it
this way
set TEMP=c:\temp
echo y | del %temp%\*.*
because this depends on the variable actually getting set - and accidents do happen.
Failure of the set command causes the DEL command to delete all the files in the current
directory, which is likely to be the root of the boot drive.
ECHO, without any arguments, simply displays the echo status: either ON or OFF.
There are some cases where what appears to be correct syntax doesn't cause error messages but doesn't work either. Most of these involve conditional redirection:
for %%a in (foo) do echo %%a > baz
if not !%1 == ! echo foo > bar
don't work, at least not reliably. It is far safer to put the redirected echo command somewhere else and get at it with a CALL or to jump over the echo with an inverted conditional GOTO:
if !%1 == !}{ goto %2
for %%a in (foo) do call %0 }{ report %%a
if !%1 == ! goto cont
echo foo > bar
:cont
goto end
:report
echo %3 > baz
:end
The FOR x in (set) do
command has many uses. It appears that
the original intent appears to be to return file names in a list or matching a pattern one at a time,
and it is still very useful for that sort of work:
@echo off
for %%a in (*.bat) do if not exist .\bak\%%a copy %%a .\bak
:end
makes sure that there is a backup copy of each of the batch files in the default
directory, but copies only the ones that don't already have backups. It doesn't
check to see if they are the same, but the backups may well be intended to be
the previous versions. Note that the variable is a single letter
preceded by double '%' signs. One of these is stripped off during command processing,
so the real name is "%a", which is what you use when using this syntax from the
command line. (It is not essential that the variable name use a letter, but numbers
are forbidden and the convention is to use letters that mean something or are in
alphabetic order (for multiple uses of FOR in the same file).
FOR also has other uses, for example, to process a list of items:
for %%a in (*.bat *.exe, *.com) do if not exist .\bak%%a copy %%a .\bak
does what the first example does, except for all three of those extensions.
The list (set) need not have anything to do with files, as the following three digit counter illustrates:
@echo off
if "%1" == "}{" goto %2
set target=%1
command /e:1024 /c%0 }{ pass0
goto end
:pass0
for %%a in (0 1 2 3 4 5 6 7 8 9) do call %0 }{ pass2 %%a
goto end
:pass2
for %%b in (0 1 2 3 4 5 6 7 8 9) do call %0 }{ pass3 %3 %%b
goto end
:pass3
for %%c in (0 1 2 3 4 5 6 7 8 9) do call %0 }{ pass4 %3 %4 %%c
goto end
:pass4
set count=
:loop1
if "%3" == "" goto done
REM - uncomment the following line to enable leading zero suppression
REM if "%3" == "0" if "%count%" == "" goto x1
set count=%count%%3
:x1
shift
goto loop1
:done
if "%count%" == "" goto end
:usercode
REM user specific code to use the number goes here
:userend
if "%target%" == "%count%" exit
:end
This was written in response to a question about how to rename files with
consecutive numbers. It accepts a target number beyond which it will not
count as an argument, and the user code would use the file name passed as
the second argument as the file to rename. The user code would generate the
name and test for the existence of a file with that name, continue to loop
as long as there was one, and exit after finding the first unused number.
I omitted that code since it was specific to one particular user.
Note that if you are using leading zeros (the default) the target argument
must be exactly three digits long - use leading zeros for one and two digit numbers.
A more usable form of the above (called RENnnn.BAT) takes five arguments: the name of the file to rename, and (optionally) the prefix to put in front of the number, the extension to apply, the limiting number and a path to apply to the given filename. If no limit is given, the default is 999. Obviously, if any of the later options are used, the earlier ones must also be supplied - ',' can be used to indicate that an argument is a null.
@echo off
if "%1" == "}{" goto %2
set target=%999
set fname=%1
set prefix=%3
set ext=%4
set dir=%2
if !%5==! goto begin
set fname=%dir%\%fname%
command /e:1024 /c%0 }{ pass0
goto endcount
:pass0
for %%a in (0 1 2 3 4 5 6 7 8 9) do call %0 }{ pass2 %%a
goto endcount
:pass2
for %%b in (0 1 2 3 4 5 6 7 8 9) do call %0 }{ pass3 %3 %%b
goto endcount
:pass3
for %%c in (0 1 2 3 4 5 6 7 8 9) do call %0 }{ pass4 %3 %4 %%c
goto endcount
:pass4
set count=
:loop1
if "%3" == "" goto done
REM - uncomment the following line to enable leading zero suppression
REM if "%3" == "0" if "%count%" == "" goto x1
set count=%count%%3
:x1
shift
goto loop1
:done
if "%count%" == "" goto endcount
:usercode
if exist %dir%\%prefix%%count%.%ext% goto userend
if not exist %fname% exit
echo Copying %fname% to %dir%\%prefix%%count%.%ext%
copy %fname% %dir%\%prefix%%count%.%ext%
echo Deleting %fname%
del %fname%
exit
:userend
if "%target%" == "%count%" exit
:endcount
Note that the passed prefix can contain a path and or a base (relative to the given directory) for the new name itself. This version does nothing if the target file already exists or if the given file does not exist.
Note that all these numerical renaming programs start with 000 as the first number. the code can be modified to start at any number by creating an environment variable containing the starting number (with leading zeros if you are using them) and modifying the usercode section to this
:usercode
if !%startnum% == ! goto cont
if !%startnum% == !run goto cont
if not !%startnum% == !%count% goto userend
set startnum=run
:cont
if exist %dir%\%prefix%%count%.%ext% goto userend
if not exist %fname% exit
copy %fname% %dir%\%prefix%%count%.%ext% > nul
del %fname%
exit
:userend
Note that "> nul" has been added to the copy command and the two announcements have been removed - those modifications remove all screen messages except error messages.
Another use of FOR is as a loop counter:
for %%a in (! ! ! ! ! ! ! ! ! !) do something
does whatever you tell it to ten times, once for each bang character in the
set.
A more elaborate bang counter that takes a numerical argument (0 - 10) is
@echo off
set target=
if %1!==0! set target=
if %1!==1! set target=!
if %1!==2! set target=!!
if %1!==3! set target=!!!
if %1!==4! set target=!!!!
if %1!==5! set target=!!!!!
if %1!==6! set target=!!!!!!
if %1!==7! set target=!!!!!!!
if %1!==8! set target=!!!!!!!!
if %1!==9! set target=!!!!!!!!!
if %1!==10! set target=!!!!!!!!!!
set count=
shift
:loop
if %count%!==%target%! goto end
set count=%count%!
REM user code goes here - comment out or remove the following line
REM if you don't want to see the count process.
echo %count%
goto loop
:end
Obviously that can be used only for rather small numbers, a small range of numbers
or a small number of non-sequential numbers. These fragments (just the translation
code) illustrate the latter two uses:
@echo off
set target=
if %1!==23! set target=!!!!!!!!!!!!!!!!!!!!!!!
if %1!==24! set target=!!!!!!!!!!!!!!!!!!!!!!!!
if %1!==25! set target=!!!!!!!!!!!!!!!!!!!!!!!!!
if %1!==26! set target=!!!!!!!!!!!!!!!!!!!!!!!!!!
@echo off
set target=
if %1!==1! set target=!
if %1!==9! set target=!!!!!!!!!
if %1!==23! set target=!!!!!!!!!!!!!!!!!!!!!!!
There is also the undocumented syntax (completely broken in Win95 and NT) that places a '/' in front of a string. This syntax has the curious property of calling the DO clause twice - once with the character following the '/', and the second time with the rest of the string. This is handy for stripping leading characters and for reformatting strings. The following code strips the first four digits off a twelve digit Ethernet address to make an eight digit string for use as a directory name:
@echo off
%1 %2 %3 %4 REM You are not expected to understand this batch file
goto pass0
:pass1
for %%b in (/%SHRTNM%) do call %0 goto pass2 %%b
goto end
:pass2
goto pass2%pxt%
:pass2a
set pxt=b
goto end
:pass2b
set pxt=a
set shrtnm=%3
goto end
:pass0
set pxt=a
REM network installation code omitted - it generates the value of STATION
REM as the Ethernet address
set shrtnm=%STATION%
for %%a in (1 2 3 4) do call %0 goto pass1
set pxt=
REM more code omitted
:end
That is an edited version of a real batch file - the comment is for the benefit
of users who don't have enough to do to keep them busy without messing around with
the machine's configuration and setup files.
Other examples of the use of FOR can be found throughout this book, but there is in interesting use for reversing a string and adding spaces in the section on Decimal Addition.
GOTO
is the command we are taught to avoid in structured
programming. Well, we don't really have a choice in batch language, since if
we want structured code, we have to write the structures using GOTO. Basically,
GOTO is a jump within a batch file.
There are plenty of examples throughout the code here. If the target is below
the jump, COMMAND.COM need only read and parse the lines between the jump and the
target, but if it is above the jump, COMMAND.COM must read to the end, then
start over. For large backward jumps, it is well to reinvoke the batch file and
have a vector at the top to handle the actual jump,
which is then a forward jump:
@echo off
%1 %2
:label1
REM some code
%0 goto label1
REM more code
:end
Note that either a space or a colon can be used as the separator between "goto" and the target label. This is particularly useful in constructions involving FOR:
for %%a in (echo goto:end) do %%a Message
will first echo the message then goto the :end label.
IF ERRORLEVEL
is normally used to cause the batch file to take the
appropriate action based on the success or failure of an external
executable program, though it can, in some cases, be used to select
the proper code based on the nature of the failure.
The only available test for use with ERRORLEVEL is an
if errorlevel => x test (and it's negation,
of course). ERRORLEVEL cannot be assigned to a variable.
The standard forms of the test are
if errorlevel 4 goto el4
if errorlevel 3 goto el3
if errorlevel 2 goto el2
if errorlevel 1 got0 el1
Note that the highest number of interest must be tested first because the
test returns true for any value equal to or greater than the test value.
The form
if not errorlevel 4 goto nel4
performs a < test.
if errorlevel 4 if not errorlevel 5 got el4
and similar constructs perform an exact equality test.
A special case is the kind of program that returns information, such as what key was pressed, as the ERRORLEVEL.
@echo off
xcopy e:\temp\*.* c:\temp\ /s
if not errorlevel 1 goto success
echo No files found to copy or XCOPY failed
goto end
:success
... do whatever you need to do with the copies
:end
Note that if the /a switch had been used with XCOPY, ERRORLEVEL 0
would not necessarily mean that it copied any files, only that some
files were found before the archive attribute was checked.
IF EXIST foo
allows executation of a command, conditional on the existence of a
named file. The filespec and or the command can be variable, but here
we address the hard coded case.
if exist foo del foo
is a common usage of the IF EXIST construct. It avoids the "File not
found" error message if the file given by foo does not exist, by
attempting to delete the file only if it actually exists. This is
frequently used with foo being a wild card pattern. A number of
variations of this single conditional executation construct are given
in the Examples section. The negation can
also be used to verify that a file does not exist before doing something
that requires that condition:
if not exist foo.bat copy \bin\foo.bat
The command in the IF EXIST construct can be CALL or GOTO, which allow something like procedure and function calls. While the first example generate syntax errors if the negation operator is used, commands that do not act on the file tested do not, and use of negation can often simplify the structure. Here a real world example is used, though only in outline form: it is frequently necessary to determine if some external utility succeeded, but the utility does not return a useful ERRORLEVEL - the output from the command can be filtered through FIND, FIND's output routed to a file, and the file tested for content by attempting to copy it. This code determines in the file TEST.DAT contains the phrase "the quick brown fox" (using the case insensitive match feature of FIND).
@echo off
set response=Phrase not found
find /i "the quick brown fox" test.dat > }{.1
copy }{.1 }{.2
if not exist }{.2 goto done
del }{.2
set response=Phrase found
:done
del }{.1
echo %response%
set response=
:end
Note that if the negation operator (NOT) had not been used, it would
have been necessary to apply special handling to the deletion of }{.2,
or to use a more complicated structure with multiple jumps, rather
than the fall through structure actually used, as in this example
@echo off
find /i "the quick brown fox" test.dat > }{.1
copy }{.1 }{.2
if exist }{.2 goto exists
echo Phrase not found
goto done
:exists
echo Phrase found
del }{.2
:done
del }{.1
:end
IF foo == bar
does string comparisons.
The strings can be command line arguments, environment variables, or string literals.
A very old example
is the RUN.BAT program that combines a number of batch files into one
and uses the first command line argument to vector to the code needed
for the case in hand.
@echo off
if "%1" == "ed" goto ed
if "%1" == "c" goto c
echo ERROR: the %1 argument cannot be identified.
goto end
:ed
... code to set up for, launch, and clean up after the text editor
goto end
:c
... code to set up for, launch, and clean up after the c compiler and its IDE
goto end
:end
A common use is to control program flow on the basis of environment variables:
if "%temp%" == "" goto novar
(The "" marks allow comparison of null strings since they become part of the
string - if %temp% has not been set to something, the above becomes ""=="" after
normalizing and substituting by the command processor.
A variation is to convert the argument(s) to all caps before making the comparison - see: "Examples". The variable command syntax (to be elaborated later) can be used here as well.
MOVE has some uses that aren't obvious from its name, but parallel some of the functionality of the unix version: it not only moves files but also renames directories - but it won't move directories. MOVE takes only one switch: /y (or /-y to override a /y switch in the COPYCMD variable (both COPY and MOVE use the same variable so they have to have the same switches active for both)). The syntax is
MOVE [/Y | /-Y] [drive:][path]dirname1 dirname2
(as given my MS) but more correctly
MOVE [/Y | /-Y] [drive:][path]dirname1 [drive:][path]dirname2
for renaming (but not moving) a directory - note that the optional parts of
the syntax have to appear in both source and target specs if they are used in
either and have to be the same in both.
MOVE [/Y | /-Y] [drive:][path]filename1[,...] destination
Moves and/or renames a file. "destination" can be almost anything that makes sense, but
if the destination doesn't exist and is like a filename it will be taken as a
filename in the current directory - if the file is in the current directory
the result is the same as a REN. If the file is not in the
current directory it will be moved there. If everything is specified and the target
directory exists, the file will be moved there, even to a different drive. MOVE is an
external command (MOVE.EXE) and returns errorlevels: 0 for success and 1 for error. This
may have some subtle uses in batch files, but I haven't had the time to explore the implications.
There is quite a bit on information in HELP about MOVE, and most of it is correct though (of course) incomplete.
Useful things you can do with the PROMPT
There are two categories of things to do with the PROMPT command: issue strings containing hard to deal with Escape characters to the console and obtain information for use in the batch file (or elsewhere). The former is most frequently used to send ANSI Escape sequences to ANSI.SYS (a replacement console device). This is easy:
@echo off
set oldprompt=%prompt%
prompt $e[2J
echo on
@echo off
set prompt=%oldprompt%
set oldprompt=
:end
clears the screen. The Escape sequences are more often used to control
colors and/or cursor position, though - just change the part after "$e["
to whatever you need.
Since we want the changed prompt to be active only once, we save the old string, turn echoing on, generate a pure prompt with a blank line, then turn echoing off again, and restore the original prompt string.
Using the prompt to get information is a bit trickier, since we have to redirect the prompt into a file, and that can't be done, except by spawning a secondary command processor and redirecting its output, which leaves us with the problem of getting the information back into the program:
@echo off
%1 %2
set oldprompt=%prompt%
prompt %0 goto pass2 $d $t
command /c%0 goto dummy > }{.bat
set prompt=%oldprompt%
set oldprompt=
}{
goto end
:pass2
set stamp=%4/%5
goto end
:dummy
echo on
@echo off
:end
generates a date/time stamp of the form 09-09-1995/19:39:05.29 (you could
strip off just the characters form the time that you wanted with some of
the string processing code found in many of the examples here and elsewhere
in this book. Note that %3 is omitted from the stamp: it is the day name.
The problem of getting the information back into the batch file is dealt with here by including the necessary commands to reinvoke the batch file and vector it to the proper section of code in the changed prompt string, and therefore in the batch file that the prompt is redirected to. The invocation of COMMAND.COM with the arguments given causes it to reinvoke the batch file and vector to the section that turns echoing back on, generates a prompt with a blank line, then turns echoing back off, and exits (which causes the secondary command processor to terminate as well, which returns us to the line following the invocation of the command processor. As in the earlier example, we have to save and restore the original prompt string. The changes should be effective for as few commands as possible, so that if the program abends, the chances of having a corrupt prompt are low, though in reality, the only place where an abend is likely (from a user issued ^C) is when the changed prompt is being written to the file. However, during testing, with all echoing enabled, ^C would be active everywhere, and would also be quite likely to occur.
Variations on this theme give you the day name from $d and %3, the DOS version from $v and %5, the drive letter from $n and %3, or the drive and path with $p and %3.
I have seen a batch file that does all of this at once, putting the various elements into separate environment variables (the structure was completely different, and rather interesting, but not quite my style).
Redirection and pipes are operators, not commands. They tell COMMAND.COM to connect the input or output of programs to either files (redirection) or other programs (pipes). This works only if the program uses the standard input and output streams for its console I/O. In general, programs with fancy screens don't and those with crude command line interfaces do. Most DOS utilities do. Nearly all filters do (MORE is a filter).
Pipes use the | symbol to connect the output of one program or command to
the input of another. Quite long chains can be built this way. A very common use is
to pipe the output of a command or program through FIND to strip out everything except the
specific line(s) wanted.
The input redirection operator is < and the output redirection
operators are > and >>. < connects a file (or device)
to the input stream of a program so that you can put responses to prompts in a file and
run the program automatically. Input redirection is seldom used these days because
few programs use the standard input stream (STDIN) and few users understand the benefits.
It is used in this book most often in the LOADFIX/DATE method
of working with lists. Output redirection is more generally used - it is useful for
putting directory listings into files and for creating and filling files from inside
batch programs, using the ECHO command and redirection to change the destination of
the ECHO to a file instead of the console. > causes the file to be created or truncated -
multiple ECHOs to the same file will leave the file with just the last one in it while
>> causes whatever is redirected to be appended to the end of the file. >> is
useful for building batch files from within batch files: the file is created with a >
redirection and the remaining ECHO lines use >> to add the lines to the end of
the file. >> is also useful for creating and adding to log files:
echo. | date | find "Current" >> foo.log
echo. | time | find "Current" >> foo.log
echo. >> foo.log
assumes that the user will delete or rename the file from time to time - otherwise
it can grow to fill the drive. It puts just the date line ("Current date is ...") and
the time line ("Current time is ...") followed by a blank line into the log file.
The ECHO. command generates just an <Enter> which is piped to the DATE and TIME
commands to respond to the "Enter new ..." prompts that would otherwise stop the program
and wait for the user to hit <Enter>. The third use causes a blank line to be
appended to the end of the file. The same effect can be had, though more slowly,
by creating a file containing just a blank line and redirecting it to the input
of the DATE and TIME commands and TYPEing it to the target file:
date < response.fil | date | find "Current" >> foo.log
time < response.fil | date | find "Current" >> foo.log
type response.fil >> foo.log
Note that output redirection and pipes work only with the standard output stream (STDOUT) and the standard input stream (STDIN).
There are many gotchas and subtleties to redirection and pipes: in complex commands
only the output of the first command is redirected, and that is often something like
"if exist or FOR that doesn't even have an output in the
usual sense. Sometimes this effect is useful, but more often it's a nuisance. One
time when it is very useful is when it is desirable to put the total output from a
batch file into a file or through a filter. In that case, the batch file is run
from a secondary command processor and the output of that is redirected or piped.
See the section on Debugging batch files, and the DIRX.BAT program
for more explanation and examples. The latter works around most of the gotchas that
afflict redirection and pipes
REM
is the comment (REMark) marker. "::" works
better for pure comments (that's really a defective label, and isn't processed at
all), but REM actually has uses a a command:
@echo off
REM > temp.tmp
:echo
has the remarkable property of creating a zero length file named TEMP.TMP, which can
then be used in an IF EXIST test, where it will test as existing, but doesn't actually
consume disk space, only a directory entry. The curious thing about that use of REM is
that you can still include a comment string in the remark without having it go into
the target file.
@echo off
REM this is a test > temp.tmp
:end
still creates a zero length file named TEMP.TMP.
The standard syntax is @echo off REM this is a comment :end which has no effect on the program except to slow it down slightly more than the "::" syntax:
@echo off
:: this is also a comment, though COMMAND.COM thinks it's a defective label
:end
Note: it has been reported in newsgroups that ';' is also a comment marker - this
is not true for MSDOS 6.22.
REN and RENAME are variant names for the same command - the command to rename files (but not directories - use MOVE for that.
The usage and syntax are both simple and it's functionality is very limited. The syntax is
RENAME [drive:][path]filename1 filename2
REN [drive:][path]filename1 filename2
and the effect is to change just the name and/or extension of the specified file(s) -
you cannot change the directory part of a filespec with REN - you can't even specify
a path in the target filename. This function will rename zero length files - it
works only on the directory entry and doesn't care what, if anything, is in the file.
There isn't much that can be done with the command other than its intended use.
REN and RENAME are internal COMMAND.COM functions and therefore return no errorlevel.
SHIFT
has only one function: it relocates the
window of accessibility of command line arguments toward the end of the
command tail. The only arguments ever available are %0 through %9. Initially
%0 is the first thing on the command line (the name of the program) and the
arguments %1 through %9 are the next nine fields on the command line (the first
nine arguments to the program). SHIFT moves this access window one
position to the right (or conversely, the arguments one position to the left)
so that each argument refers to the item that was to its right. This is
used in Decimal Addition to position the ten
items in the look up table so that they line up with the digits 0 through 9
for indexes [0] through [9]. This batch file (name it ZERO.BAT) illustrates the concept by
reinvoking itself with an argument string and shifting through it (%10 is included
to show that %9 really is the upper limit - %10 resolves to %1 followed by
a literal '0' character):
ZERO.BAT
@echo off
%fork%
set fork=goto pass2
%0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
:pass2
echo.
echo Unshifted:
echo %%0=%0 %%1=%1 %%2=%2 %%3=%3 %%4=%4
echo %%5=%5 %%6=%6 %%7=%7 %%8=%8 %%9=%9
echo %%10=%10
echo.
shift
echo Shifted once:
echo %%0=%0 %%1=%1 %%2=%2 %%3=%3 %%4=%4
echo %%5=%5 %%6=%6 %%7=%7 %%8=%8 %%9=%9
echo %%10=%10
echo.
shift
echo Shifted twice:
echo %%0=%0 %%1=%1 %%2=%2 %%3=%3 %%4=%4
echo %%5=%5 %%6=%6 %%7=%7 %%8=%8 %%9=%9
echo %%10=%10
echo.
shift
echo Shifted three times:
echo %%0=%0 %%1=%1 %%2=%2 %%3=%3 %%4=%4
echo %%5=%5 %%6=%6 %%7=%7 %%8=%8 %%9=%9
echo %%10=%10
echo.
shift
shift
shift
shift
echo Shifted seven times:
echo %%0=%0 %%1=%1 %%2=%2 %%3=%3 %%4=%4
echo %%5=%5 %%6=%6 %%7=%7 %%8=%8 %%9=%9
echo %%10=%10
echo.
shift
shift
shift
shift
shift
echo Shifted twelve times:
echo %%0=%0 %%1=%1 %%2=%2 %%3=%3 %%4=%4
echo %%5=%5 %%6=%6 %%7=%7 %%8=%8 %%9=%9
echo %%10=%10
echo.
set fork=
:end
There are a few other commands that are seldom used outside of batch files. Some, such as LOADHIGH, SUBST, SETVER, and the like are system setup commands, and really don't have a place in a discussion of batch files as batch files, but belong in discussions of system configuration - they will be ignored in this treatise. There is one other, SET, which while technically a COMMAND.COM internal command, rather than a batch file intrinsic command, will be treated here because it is seldom used from the command line and is essential to the operation of the majority of batch files.
SET
is the command that places a string into a named record
in the environment. It is discussed more fully in the
section devoted to Variables, and is illustrated
throughout this treatise.
** Copyright 1995, Ted Davis - all rights reserved **
Input and feedback from readers are welcome. NOTE: the subject of the message must contain the word "batch" for the message to get past the spam filter.
Back to the Table of Contents page
Back to my personal links page - back to my home page