16
votes

How do I create a batch file to delete files older than a specified date?

This does not seem to work;

:: --------DELOLD.BAT----------
@echo off
SET OLDERTHAN=%1
IF NOT DEFINED OLDERTHAN GOTO SYNTAX

for /f "tokens=2" %%i in ('date /t') do set thedate=%%i
type %1
pause
set mm=%thedate:~0,2%
set dd=%thedate:~3,2%
set yyyy=%thedate:~6,4%

set /A dd=%dd% - %OLDERTHAN%
set /A mm=%mm% + 0

if /I %dd% GTR 0 goto DONE
set /A mm=%mm% - 1
if /I %mm% GTR 0 goto ADJUSTDAY
set /A mm=12
set /A yyyy=%yyyy% - 1

:ADJUSTDAY
if %mm%==1 goto SET31
if %mm%==2 goto LEAPCHK
if %mm%==3 goto SET31
if %mm%==4 goto SET30
if %mm%==5 goto SET31
if %mm%==6 goto SET30
if %mm%==7 goto SET31
if %mm%==8 goto SET31
if %mm%==9 goto SET30
if %mm%==10 goto SET31
if %mm%==11 goto SET30
if %mm%==12 goto SET31

goto ERROR

:SET31
set /A dd=31 + %dd%
goto DONE

:SET30
set /A dd=30 + %dd%
goto DONE

:LEAPCHK
set /A tt=%yyyy% %% 4
if not %tt%==0 goto SET28
set /A tt=%yyyy% %% 100
if not %tt%==0 goto SET29
set /A tt=%yyyy% %% 400
if %tt%==0 goto SET29

:SET28
set /A dd=28 + %dd%
goto DONE

:SET29
set /A dd=29 + %dd%

:DONE
if /i %dd% LSS 10 set dd=0%dd%
if /I %mm% LSS 10 set mm=0%mm%
for %%i in (*.*) do (
set FileName=%%i
call :PROCESSFILE %%~ti
)

set mm=
set yyyy=
set dd=
set thedate=
goto EXIT

:SYNTAX
ECHO.
ECHO USAGE:
ECHO DELOLD X
ECHO   Where X is the number of days previous to Today.
ECHO.
ECHO EX: "DELOLD 5" Deletes files older than 5 days.
GOTO EXIT

:PROCESSFILE
set temp=%1
set fyyyy=20%temp:~6%
set fmm=%temp:~0,2%
set fdd=%temp:~3,2%
if /I %fyyyy% GTR 2069 set fyyyy=19%temp:~6%


:: ***************************************
:: * This is where the files are deleted *
:: * Change the ECHO command to DEL to   *
:: * delete. ECHO is used for test.      *
:: ***************************************
if /I %yyyy%/%mm%/%dd% GEQ %fyyyy%/%fmm%/%fdd% (
ECHO %FileName%
)

set temp=
set fyyyy=
set fmm=
set fdd=

:EXIT

:: ----------END-DELOLD.BAT-------------
8
A new method based in a .BAT file that use internal CMD.EXE commands only has been posted here: stackoverflow.com/questions/9746778/… - Aacini
I don't agree this is a duplicate question... it is similar but not the same: removing files older than a given date vs files older than N days, to use the second in implies computing the amount of days between two dates, which is not trivial in a batch file - cbuchart

8 Answers

10
votes

I use this script:

////////////////////////////////////////////////////////
// Deletes file older than a number of days 
// in the current directory
////////////////////////////////////////////////////////
// Usage: wscript DeleteOlderThan.js [#Days]
// By default, remove files older than 30 days
////////////////////////////////////////////////////////

function removeDays(date, nDays)
{
    var dateRet = date
    return dateRet.setDate(date.getDate() - nDays);
}

function addSlash(strPath)
{
    var c = strPath.substr(-1, 1);
    if( c !== '\\' && c !== '/' )
    {
        strPath += '\\';
    }
    return strPath;
}

// Read arguments
var nDays = WScript.Arguments(0) || 30;

// Create system objects
var fs = WScript.CreateObject("Scripting.FileSystemObject");
var shell = WScript.CreateObject("WScript.Shell");

// Retrieve current directory
var strDirectoryPath = addSlash(shell.CurrentDirectory);

// Compute date
var dateNow = new Date();
var dateTest = removeDays(dateNow, nDays);

// Iterate on files
var folder = fs.GetFolder(strDirectoryPath);
var files = folder.Files;

for( var it = new Enumerator(files); !it.atEnd(); it.moveNext() )
{
    var file = it.item();

    if( file.DateLastModified < dateTest)
    {
        file.Delete(true);
    }
}

which I invoke every day with:

wscript "C:\Program Files\Utils\DeletesOlderThan.js" 30
10
votes

If you're on a Windows Server and/or have the Server Resource Kit installed, forfiles may be exactly what you're looking for.

Examples: print all file names, older than 180 days

forfiles /S /D -180 /C "cmd /C Echo @Path" >olderthan180days.txt

delete all PDF files, older than 365 days

forfiles /S /M *.pdf /D -365 /C "cmd /C Del @Path"
7
votes

Edit: I figured it out.

To delete all files older than a given date:

REM del_old.bat
REM usage: del_old MM-DD-YYY
for /f "tokens=*" %%a IN ('xcopy *.* /d:%1 /L /I null') do if exist %%~nxa echo %%~nxa >> FILES_TO_KEEP.TXT
for /f "tokens=*" %%a IN ('xcopy *.* /L /I /EXCLUDE:FILES_TO_KEEP.TXT null') do if exist "%%~nxa" del "%%~nxa"

To delete all files newer than a given date:

REM del_new.bat
REM usage: del_new MM-DD-YYYY
for /f "tokens=*" %%a IN ('xcopy *.* /d:%1 /L /I null') do if exist "%%~nxa" del "%%~nxa"
7
votes

eJames: I found your xcopy solution to work very well, indeed! The thing I like most about it is that it should work in Windows language versions other than English as well, since the format of the XCOPY parameters seems to be date-setting independent. Wonderful! ;]

One improvement would be to pre-create the FILES_TO_KEEP.TXT file so that if no file match the keep criteria, the second XCOPY statement can still go ahead and do the delete (it fails if it cannot find the FILES_TO_KEEP.TXT file). Here's my script (please note in this example I changed it to only delete *.pdf files and I also changed the temp file name to make more sure there are no potential conflicts, as well as cleaning up the temp file afterwards):

@echo off
SET OLDERTHAN=%1
IF NOT DEFINED OLDERTHAN GOTO SYNTAX

echo >> ~~~FILES_TO_KEEP.TXT~
for /f "tokens=*" %%a IN ('xcopy *.pdf /d:%1 /L /I null') do if exist %%~nxa echo %%~nxa >> ~~~FILES_TO_KEEP.TXT~
for /f "tokens=*" %%a IN ('xcopy *.pdf /L /I /EXCLUDE:~~~FILES_TO_KEEP.TXT~ null') do if exist "%%~nxa" del "%%~nxa"
del ~~~FILES_TO_KEEP.TXT~

GOTO END

:SYNTAX
ECHO.
ECHO USAGE:
ECHO DELOLD mm-dd-yyyy
ECHO   Where mm-dd-yyyy is the date prior to which you want to delete files.
ECHO.
ECHO EX: "DELOLD 10-17-2008" Deletes files older than October 17, 2008.
ECHO.
ECHO This should work on any language version of Windows, but has only been 
ECHO tested in English-US versions.
GOTO END

:END
1
votes

My solution works if you

  • either have a touch utility on your system (which I do)
  • or can afford to temporarily change system date using date command (which is probably not the case, but who knows)

Here's the idea:

  1. In the target directory, create a signal file (with a unique name), and with timestamp equal to your deletion threshold time. It can be done with touch (which accepts desired timestamp as a parameter), or by remembering current date with date /T, changing system date to desired with date <param>, and restoring the original date.

  2. Use for /f %%I in ('dir /od') to iterate over all files ordered by date, deleting them one by one. After you encounter (and delete) the signal file, stop deleting.

1
votes

Perhaps you would like this: http://blog.jumlin.com/2010/10/move-files-in-folders-and-subfolders-older-than-one-year/

Thats a script that will move files older than one year, it even supports various date formats and subfolders. You could make a few changes to make it delete instead of move them. Its a very complete script with comments and explanations.

0
votes

I wonder why you have to use the ole DOS shell... Python or Windows Powershell would be the right choices in 2008 :)

-1
votes

I don't know if you can do that with .BAT files and what few tools Windows comes with, but you sure can with .js (JScript) or .vbs (VBScript) files. You are doing this under Windows, right? If so, then Windows can process .js and .vbs files just as well as .bat files by default. They are far more powerful.

And, if you happen to be targeting only Windows Server 2008, there's PowerShell which is even better (downloadable for other Windows versions).