Results 1 to 5 of 5

Thread: Batch file that will delete files older than x

  1. #1
    Junior Member
    Join Date
    Apr 2006
    Posts
    5

    Batch file that will delete files older than x

    Hey folks. I have a nightly batch file that downloads 2 files to separate archive folders that are both contained in the same parent directory. The files are just for backup purposes, and are only needed to be stored for maybe a month or two before they are no longer needed.

    So as not to have more of these backup files then are needed and using up HD space, I'm looking for a way to have the last step in my batch file delete any of the previously archived files that are older than a specified age, i.e. 2 months. Any suggestions on the code/line I can add to the batch file that might accomplish this task? Thanks in advance.

    Jim

  2. #2
    Senior Member
    Join Date
    Mar 2005
    Posts
    400
    You didn't say what operating system you are using and if using long file names.

    If using DOS, Win95 or Win98, you can use a program called Fdate to assist your batch file.

    Fdate is a 16-bit application written in Turbo Pascal, which means that it cannot process long filenames. This is becoming more and more a handicap as time goes on.

    Batch files are obsolete. Batch, as a scripting language, is grossly underpowered.

    So, although FDATE is still available, I cannot recommend using it.

    Instead, I recommend Python, an excellent open-source scripting language. It is easy to learn and use, powerful, free, well-documented, and runs on virtually every platform in existence. More information can be found at http://www.python.org. An excellent date/time module for Python is mxDateTime.

    The next post below is the solution, if not using long file names.
    ZT3000
    Beta tester of "0"s and "1"s"

  3. #3
    Senior Member
    Join Date
    Mar 2005
    Posts
    400
    Delete files more than X days old (use a batch-file subroutine)
    :==================================================================
    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%
    :: -----------------------------------------------
    REM 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%
    :: -----------------------------------------------
    REM 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
    ===============================================================
    ZT3000
    Beta tester of "0"s and "1"s"

  4. #4
    Junior Member
    Join Date
    Apr 2006
    Posts
    5
    ZT, thanks for taking the time to provide such a lengthy reply. Sorry about not providing all relevant details. My batch file runs on WinXP Pro. Unfortunately, yes, I am using long file names. My current batch file is working well, but I was hoping to extend the functionality to include deleting old files as well.

    Currently, I have a Scheduled Task executing the batch file nightly. It does the following:
    - starts ftp.exe and connects to an ftp server (UN/PW supplied in associated data file)
    - downloads 2 files to current, local directory
    - renames the two files by pre-pending current date to beginning of file names.
    - moves both files to separate subfolders that are both in the current directory

    This is working out well and I could just manually delete old files after a month or so if need be, but I was hoping to automate the cleanup through the batch file. I know batch scripting is wholly insufficient, but since I have absolutely zero programming experience/knowledge, I figured it was the lesser evil and the option with least complexity.

    I think tackling learning Python for this one small task is a greater and longer investment that I can afford for this small need, but I’m going to give a shot at looking at it since the knowledge would certainly be valuable to have in general for me.

    If you would like to suggest what the script might look like in Python in order to get me going down the right path, that would be greatly appreciated, but I understand if not, you already made a lengthy reply once, and I’m grateful. My current DOS batch script (which was created by soliciting help on forums such as this) looks like this (again, works great, just wondering how difficult it would be to add ability to delete files older than maybe 30 days from the two subfolders):

    ftp -s:C:\NewsFTP\NewsDataFile.cmd
    @echo off
    for /f "tokens=1-4 delims=/ " %%a in ('date /t') do (set weekday=%%a& set day=%%b& set month=%%c& set year=%%d)
    ren newsfeed.dat %day%_%month%_%year%-newsfeed.dat
    ren other_news.dat %day%_%month%_%year%-other_news.dat
    move C:\NewsFTP\*-newsfeed.dat C:\NewsFTP\English
    move C:\NewsFTP\*-other_news.dat C:\NewsFTP\Other


    Thanks again, and sorry for the really long post.

    Jim

  5. #5
    Senior Member
    Join Date
    Mar 2005
    Posts
    400
    I don't have an Python example of your situation (cause I'm a Python newbie), but consider this:

    Notice the lack of Python code to take any number between 0 and 25 (for this example), decide if it's divisable by three, and if divisable by three, give a remainder.

    for i in range (0,25) :
    if i == 0 :
    print i, '(zero) is not a divisable number'
    elif i % 3 == 0 :
    print i, 'is evenly divided by three'
    if i == 1 :
    print i, '(One) is not evenly divisable by three'
    elif i % 3 == 1 :
    print i, 'is divisable by three with a remainder of', i % 3
    if i == 2 :
    print i, '(Two) is not evenly divisable by three'
    elif i % 3 == 2 :
    print i, 'is divisable by three with a remainder of', i % 3

    Writing this code in any other language would be longer and more complex.


    For further help on Python,

    **Listed in the order I used them and in a perceived order of difficulty**

    1. Python Babysteps Tutorial:
    http://coolnamehere.com/geekery/python/pythontut.html

    2. Python Tutorial:
    http://martin.f2o.org/python/tutorial


    Last note: You know that huge popular MMORPG 'EVE"?? A lot of it's code in written in Stackless Python.
    ZT3000
    Beta tester of "0"s and "1"s"

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •