You can find many introduction papers to the basics of batch
programming, but this time, we'll try to go a little bit beyond
that up to recursive batch programming. But, before digressing too much, here's a quick review of common commands that you can issue within a batch.
Commands
To get help on the format of commands, type <command> /? into your command windows:
ATTRIB--Change file attributes
attrib +r+h test.txt
The previous command sets read-only and hidden
attributes on the file test.txt.
CLS--Clear the screen
EXIT--Close the command session. Self explanatory I think.
FOR--Initiate a loop. See below for a sample
FIND--Allows you to search for text in one or more files, allows you to search for specific files in memory, retrieving BIOS info. . .
GOTO--Branch flow to a known label
goto Step1
echo this one is never printed
:Step1
echo this one is printed
IF--Allows for conditional statements
if exist autoexec.bat echo Found!
The previous command prints Found! on the screen
if the file autoexec.bat is in the current dir.
MORE--Allows you to print output screen by screen
type help.txt | more
MOVE--Move a file
SET--Define environment variable
set msg="Welcome "
msg2=%msg%%username%
echo msg2
The previous batch sets one variable, creates a
second one by concatenating the first variable with the username,
and finally prints the result to the screen.
SHIFT--I'm pretty sure you were not as much aware of this one, a real nice trick, SHIFT allows you to move a parameter one step to left in a batch file.
START--Start the execution of a program in a new window. The user can select the type of window: maximized, minimized, or title, priority class for the running progam, or run it without any window. You can even WAIT for the process to terminate before executing your next batch instruction.
TYPE--Output file to default
As you can see, most of those commands are in fact little
executables that are run when requested by a batch file. Understand
that you can issue ANY command or file name in a batch file, and
it will be run. The usage of some of these commands will be explained
later.
Symbols that can be used
%--Using a % allows the use of variables inside a batch
@--Adding an at (@) in front of a command prevents the command from being echoed on the screen. For example, @DIR will execute DIR without showing the DIR command on one line.
>--Adding a > at the end of a command allows you to redirect the output. Overwriting the file in case of redirection to a file. Output can be a file result, text shown by the batch, etc. For example, DIR a: > test.txt will output content of dir into the file test.txt.
>>--Adding >> at the end of a command allows you to redirect
the output. Appending in the case of redirection to a file.
@DIR a: > test.txt ;will output content of the dir in the file test.txt)
@DIR c: >> test.txt ;will append c: dir to previous file)
NUL - Null Device. Everything that is redirected to this
devices as its output is sent to trash.
@DIR c: /s > NUL (
will output dir of the whole HD (using /s) on
NUL device. Lot of work, nothing is shown)
< - Adding a < at the end of a command allow to pass the
part at the right of the "<" symbol (command, file,
etc...) as parameter for the first command.
ex :
debug < file.txt (will send command in file.txt to the debugger)
| - Send output of the command to the input of another program
ex :
mem /c |find "MOUSE" (will execute mem /c and
send output to find.exe which
will output only lines
containing 'MOUSE')
Advanced Batching:
Now, let's play a little with basic commands we have seen before.
The FOR loop
for %%f in (*.*) do echo There is a file called: %%f
The previous command initiates a loop that searches for
all file names in the current directory (*.*). All files
found are then shown. Using this command you'll get a
list of files found in current directory. Of course,
you can be more specific in the location specification,
or in the command. The following line will silently copy
the content of %windir%repair to a floppy :
for %f in (%windir%repair*.*) do @copy %f a:
There is also a feature to use standard FOR loops
with counters
for /L %i in (1,1,5) do echo counter: %i
The /L switch specifies that we are working with numbers.
This loop will start at 1, use increment of 1, and will
do the loop up to 5. Of course you can send all results
to a file :
for /L %i in (1,1,5) do echo counter: %i > result.txt
The IF statement
The IF statement can be used to check if a condition
is true or not. This statement can work with variables,
or parameters sent to the batch:
if [%1]==[/?] goto ShowHelp
goto Continue
:ShowHelp
echo This is the help
:Continue
The IF statement can also be used in conjunction with
the 'errorlevel' variable, a variable which handles the
result of the last program executed.
RunProg.exe
if errorlevel 0 goto OK
echo We have a problem!
goto End
:OK
echo WOW! Everything went smooth!
:End
SHIFTing parameters
This can be useful when you have more than 10 parameters to pass to the batch file.
Parameters are handled by batch files through escaped digits %0...%9. %0 contain the
name of the batch file.
If you have more than 9 parameters to go through, you can use the SHIFT command. This
command will shift down each argument (%1 become %0, %2 become %1.... %9 gets a new
param). For each SHIFT, %0 disappears. Once shifted out, an argument cannot be recovered.
Recursive batch files
This one is really nifty. You can make recursive batch jobs using escaped digits. Let's take an example. I want to check all files in folder c:temp, if not existing in c:temp2
then the batch have to copy the file, then dump content to the screen (type).
echo off
%1 %2
for /F "tokens=1 delims= " %%i in ('dir /A-D /B c:temp*.*') do if not exist c:temp2%%i call %0 goto step1 %%i
goto end
:step1
COPY c:temp%3 c:temp2%3
type c:temp2%3
echo -----------------------------------------------------------------------
:end
The point here to see is : call %0 goto step1 %%i within the DO command. We just ask the
batch to call itself supplying goto and step1 as args %1 and %2. Now guess what the %1 %2
line does....
we could have done it in a much better way, like selecting in which case we have to perform the command :
echo off
if "%1" == "()" goto %2
for /F "tokens=1 delims= " %%i in ('dir /A-D /B c:temp*.*') do if not exist c:temp2%%i call %0 () step1 %%i
:step1
COPY c:temp%3 c:temp2%3
type c:temp2%3
echo -----------------------------------------------------------------------
:end
This way you can add several conditions at startup.....
Creating ASM files using batch files:
Yeah. Even creation of asm files is possible through a
batch-job. Let's see the following batch :
@echo off
echo n prog.com > file1.txt
echo a 0100 mov ah,09 >> file1.txt
echo a 0102 mov dx,0109 >> file1.txt
echo a 0105 int 21 >> file1.txt
echo a 0107 int 20 >> file1.txt
echo a 0109 db 'hello world!$ >> file1.txt
echo rcx >> file1.txt
echo 16 >> file1.txt
echo w >> file1.txt
echo q >> file1.txt
debug < file1.txt
del file1.txt
prog
At first, we are killing all echoing to the screen (echo off),
this command itself is not shown.
Then we create a file called file1.txt, of which the first line will
be 'n prog.com'. This is a command for the debugger, defining
the name of the executable to create.
We then append several lines to the file file1.txt, which contain
all assembly instruction to be compiled by the debugger (yeah,
debug.exe, one of the fabulous tools you'll be able to find
on EVERY windows installation, is also able to ASSEMBLE!!. I'm pretty sure
you'll see those little dos exe in a different way now..).
Current program will just print 'hello world' using INT 21h.
Last lines include commands for the debugger (echo w = write
file for the debugger, echo q = quit for the debugger, etc..)
Then we compile our file ( debug < file1.txt ), delete the
source and run the result.
How to close the console at the end of a batch job:
You probably have already faced those command windows that stay
wide open while the title say "Finished - xxxx". Instead of
letting the user close the window himself, you can use the
following command at the end of your batch:
@cls
When the batch is terminated, and the command screen remain
blank, the system closes the window.
Using var as modifying code:
We have seen that the use of the symbol % allow us to use
a variable as a parameter. The fun thing here is that you can
also use it as a command.
Look at the following batch:
@%sign%cls
now, define sign as an empty variable (set sign= ). Run the batch; it
will execute the command. Now if you define sign as a
command (set sign=REM), you can run the batch the line
will not be executed.
How to get a list of all .bat files on HD:
Yeah, How to do so? Everybody knows the dir /s command, for
sure, but there are more subtle ways to do it:
@echo off
chkdsk /v | find /i ".bat" > res.txt
type res.txt | more
del res.txt
The /v option of chkdsk allows us to see each filename
in every directory as the disk is checked. This list is
piped through the find command, /i parameter is used to
ignore case, and the %1 parameter specifies what we search
for. Basically, everything. Warning, this will work when
chkdsk output the file names. Won't work under NTFS.
As Find will launch a new process each time it's called,
we can't use it more efficiently. It won't work at all, in fact,
each find command outputs one line to more, which print the
line before returning to the loop. Using a temporary file
to circumvent this.
I hope having covered all what is needed to go a little beyond the
basics, if you are interested in further inspecting this area, I strongly
encourage you to turn your hear in the direction of batch virii, even if
the domain is not ethical, they contain some nasty tricks that can help
you learn a lot about what you are able to do with a batch file...
FoolFox |