.EXAMPLE.....: 41 Delete files more than X days old (use a batch-file subroutine)
.ALIAS.......: 41
.CATEGORY....: examples
.CODE........:
See the COMMENTARY that follows the text of the batch file.
@echo off
if (%1)==(SUBROUTINE) goto %2
cls
goto EndDoc
----------------------------------------------------------------------
OLDFILES.BAT
This batch file shows how to do work on files that are older than
%NumDays%. The PROCESS! subroutine can be modified to do any kind of
work you want.
----------------------------------------------------------------------
:EndDoc
:: set the number of days in the past. if this value is not passed
:: in via parameter %1, it defaults to 3 days
set NumDays=%1
if (%NumDays%)==() SET NumDays=3
echo ------------------------------------------------------------------
echo PROCESSING FILES CREATED MORE THAN %NumDays% DAYS AGO
echo ------------------------------------------------------------------
for %%v in (*.*) do CALL %0 SUBROUTINE PROCESS! %%v
echo ------------------------------------------------------------------
echo END OF PROCESSING
echo ------------------------------------------------------------------
:: CLEANUP
set NumDays=
set DaysOld=
set Comparison=
GOTO ENDIT
:PROCESS!
shift
shift
:: get difference in days between filedate and today.
:: Note that /B parm (which is omitted) defaults to today's date.
fdate /fdif /A%1 /IF /VDaysOld
:: compare DaysOld to NumDays
fdate /f#comp /A%DaysOld% /B%NumDays% /Vcomparison
:: the following line will DISPLAY THE NAME AND AGE OF
:: any file for which %DaysOld% is greater than %NumDays%
:: --------------------------------------------------------------
if (%comparison%)==(GT) echo %1 is %DaysOld% days old.
:: EXAMPLE (to activate this routine, remove the REM from column 1)
:: the following line will COPY TO AN ARCHIVE SUBDIRECTORY
:: any file for which %DaysOld% is greater than %NumDays%
:: -----------------------------------------------
:: if (%comparison%)==(GT) COPY %1 C:\ARCHIVE\*.*
:: EXAMPLE (to activate this routine, remove the REM from column 1)
:: the following line will DELETE
:: any file for which %DaysOld% is greater than %NumDays%
:: -----------------------------------------------
:: if (%comparison%)==(GT) DEL %1
:: fall through to endit
:endit
===============================================================
COMMENTARY BEGIN
===============================================================
This batch file uses a crude, but effective, technique for giving a
batch file the ability to call subroutines. If you've never seen
something like this before, it is sort of mind-blowing. Here's some
commentary on the more important lines involved in the technique.
===============================================================
if (%1)==(SUBROUTINE) goto %2
COMMENTARY:
If the first parameter, %1, is "SUBROUTINE", then the batch file
recognizes that it is being called for the purpose of executing
one of its own subroutines. In such a case, it does a GOTO to the
start of the requested subroutine. That is, it goes to the label
whose name is in the second parameter.
Explicitly specifying the name of the desired subroutine permits
permits us to have multiple subroutines in the batch file,
each with its own name. (As it happens, in this batch file
we have only one subroutine, named "PROCESS!")
If the first parameter is not "SUBROUTINE", then we fall through
and begin executing the main routine of the batch file. In such a
case, the first parameter (%1) may contain a number, indicating
the number of days to use in determining which files to delete.
Note that this technique will make the batch file malfunction
if the user himself ever executes the batch file from the
DOS command line with the word "SUBROUTINE" as the first
parameter, the word "PROCESS!" as the second parameter, and a
third parameter that is missing or not a valid filename.
This is so unlikely, however, that it is reasonable
to assume that it will never happen.
===============================================================
for %%v in (*.*) do CALL %0 SUBROUTINE PROCESS! %%v
COMMENTARY:
In a batch file, %0 contains the name by which the batch file was
invoked. We use this fact to allow a batch file to call itself,
regardless of what name the user has given to it.
The first parameter passed, when the batch file calls
itself, is the string "SUBROUTINE". This string allows the batch
file to recognize when it is being called for the purpose of
executing one of its own subroutines.
The second parameter is the name of the subroutine that we want
to call: in this case, "PROCESS!".
The third parameter is what we would normally think of as the first
parameter to the subroutine. In this case, when the
FOR statement is executed, and the substitution for %%v takes
place, it will contain the name of the file to be processed.
Note that we could, if we wished, pass additional parameters to
the subroutine. Note also that we can control the files that
we process. We do so via the filemask in the FOR statement.
It we used, for example, "*.EXE", then we would process only
executable files.
===============================================================
GOTO ENDIT
COMMENTARY:
When the mainline of the batch file is finished executing, we
goto the end of the batch file. We MUST do this GOTO in order
to avoid falling through into, and starting to execute, the first
of the batch file's subroutines.
===============================================================
:PROCESS!
shift
shift
COMMENTARY:
Note that when the batch file is called as a subroutine, and the
batch file goes to the PROCESS! label, the values of the parms are:
%0 = [the name of the batch file]
%1 = SUBROUTINE
%2 = PROCESS!
%3 = [name of the file to be processed]
We shift all the parameters to the left twice, to move the
parameter(s) into what we think of as the
proper places for parameters to the subroutine.
After the first SHIFT command:
%0 = SUBROUTINE
%1 = PROCESS!
%2 = [name of the file to be processed]
After the second SHIFT command:
%0 = PROCESS!
%1 = [name of the file to be processed]
Now %1 contains what we think of as the proper parameter(s)
to the subroutine. In this case, %1 contains the filename that
we want the subroutine to process.
At the end of every subroutine, there should be a GOTO ENDIT,
which causes the batch file to go to its own end, and then
end and return control to the statement in the program which called
it. (This is, of course, the CALL statement embedded in the
FOR statement.)
We can optimize the batch file a little by omitting the "goto endit"
at the end of the last subroutine. Instead, we simply allow the
last subroutine to fall through to the end of the batch file.
===============================================================
COMMENTARY END
===============================================================