Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

A batch file that deletes files by age in a directory with multiple subdirectories

Posted on 2004-11-11
9
Medium Priority
?
3,023 Views
Last Modified: 2012-06-27
I need a batch file that will delete files from a directory and it's subdirectories that are older than 30 days.  I can't use the deltree command because there are files younger than 30 days that need to stick around.  I also don't want the .bat file to have to be in the directory because I don't want it deleting itself.  This is what I have so far but it only deletes files from the main directory and won't delete any from the subdirectories.

:: ---------------EXAMPLE.BAT-----------------
@ECHO on
:: Change directory
cd C:\Documents and Settings\user\Desktop\test\
:: ------------
:: This is where you set the number
:: of minutes you want subtracted
:: from the current date/time.
:: ------------
SET MyDays=30

:: ------------
:: Get current date/time
:: ------------
FOR /F "TOKENS=2-4 DELIMS=/ " %%F IN ('DATE /T') DO (
 SET YYYY=%%H
 SET MM=%%F
 SET DD=%%G
)

IF %DD% LSS 10 (SET DD=%DD:~1%)
IF %MM% LSS 10 (SET MM=%MM:~1%)

: ------------
:: Subtract days from current date.
:: ------------
SET /A DD=%DD% - %MyDays%

:: ------------
:: Do the massively painful
:: reverse calculations.. :(
:: ------------
:LoopDate
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 LoopDate
:SET30
set /A dd=30 + %dd%
goto LoopDate
: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 LoopDate
:SET29
set /A dd=29 + %dd%
goto LoopDate
:DONE
IF %dd% LSS 10 set dd=0%dd%
IF %mm% LSS 10 set mm=0%mm%

for %%i in (*.*) do (
 set FileName=%%i
 SET FTIME=%%~ti
 CALL :PROCESSFILE
)

set mm=
set yyyy=
set dd=
set thedate=
goto :EOF

:PROCESSFILE
set fyyyy=%FTIME:~6,4%
set fmm=%FTIME:~0,2%
set fdd=%FTIME:~3,2%

if /I %fyyyy% GTR 2069 set fyyyy=19%FTIME:~6,2%

:: +*************************************+
:: | 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% (
  DEL %FileName%"
  ECHO Delete %FileName%
)
ECHO Cacldate=%yyyy%%mm%%dd%

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

:EXIT
:: ----------END-EXAMPLE.BAT-------------

Please Help
0
Comment
Question by:whiting002
  • 5
  • 3
9 Comments
 
LVL 30

Accepted Solution

by:
SteveGTR earned 1400 total points
ID: 12561996
Can your for loop from:

for %%i in (*.*) do (
 set FileName=%%i
 SET FTIME=%%~ti
 CALL :PROCESSFILE
)

to:

for /f "delims=" %%i in ('dir /s /b /a-d 2^>NUL') do (
 set FileName=%%i
 SET FTIME=%%~ti
 CALL :PROCESSFILE
)

Good Luck,
Steve
0
 
LVL 23

Expert Comment

by:Danny Child
ID: 12564189
try the FORFILES.EXE server resource kit tool

example:
FORFILES -p"C:\Documents and Settings\user\Desktop\test" -s -m*.* -d-30 -c"CMD /C del @FILE"

-p = path
-s = include subdirs
-m = match filetype
-d = age in days (can also be set as an absolute date ie DDMMYYYY)
-c = command to execute

Note there are no spaces between the switches and their arguments.
info here:
http://www.jsiinc.com/SUBL/tip5600/rh5645.htm
Download it here:
http://www.dynawell.com/support/ResKit/winnt.asp
0
 
LVL 2

Author Comment

by:whiting002
ID: 12564494
Steve,

I tried your suggestion but now nothing deletes.

Dan
0
Get free NFR key for Veeam Availability Suite 9.5

Veeam is happy to provide a free NFR license (1 year, 2 sockets) to all certified IT Pros. The license allows for the non-production use of Veeam Availability Suite v9.5 in your home lab, without any feature limitations. It works for both VMware and Hyper-V environments

 
LVL 2

Author Comment

by:whiting002
ID: 12565065
DanCh99,

I was hoping to keep this as a normal batch file without any extra dependencies.  I figure this has to be an issue people have been facing for years and there has to be a solution out there.

Dan
0
 
LVL 30

Expert Comment

by:SteveGTR
ID: 12565103
Place an echo statement above the date compare code:

echo if /I %yyyy%%mm%%dd% GEQ %fyyyy%%fmm%%fdd% (DEL %FileName%"  ECHO Delete %FileName%)

Let's see what it says.
0
 
LVL 2

Author Comment

by:whiting002
ID: 12565246
Steve,

I figured out why it wasn't deleting anything.  When I copied the code you provided at first, I left out a " in my delete statement.  Anyways that's taken care of but now instead of just deleting files that are 30 days or older it deletes everything.

This is what I get when the batch executes up till the deletion of the first file:
C:\Documents and Settings\jdw\Desktop\wat>cd C:\Documents and Settings\jdw\Deskt
op\test

C:\Documents and Settings\jdw\Desktop\test>SET MyDays=30

C:\Documents and Settings\jdw\Desktop\test>FOR /F "TOKENS=2-4 DELIMS=/ " %F IN (
'DATE /T') DO (
SET YYYY=%H
 SET MM=%F
 SET DD=%G
)

C:\Documents and Settings\jdw\Desktop\test>(
SET YYYY=2004
 SET MM=11
 SET DD=12
)

C:\Documents and Settings\jdw\Desktop\test>IF 12 LSS 10 (SET DD=2 )

C:\Documents and Settings\jdw\Desktop\test>IF 11 LSS 10 (SET MM=1 )

C:\Documents and Settings\jdw\Desktop\test>SET /A DD=12 - 30

C:\Documents and Settings\jdw\Desktop\test>IF /I -18 GTR 0 (GOTO DONE )

C:\Documents and Settings\jdw\Desktop\test>set /A mm=11 - 1

C:\Documents and Settings\jdw\Desktop\test>if /I 10 GTR 0 goto ADJUSTDAY

C:\Documents and Settings\jdw\Desktop\test>if 10 == 1 goto SET31

C:\Documents and Settings\jdw\Desktop\test>if 10 == 2 goto LEAPCHK

C:\Documents and Settings\jdw\Desktop\test>if 10 == 3 goto SET31

C:\Documents and Settings\jdw\Desktop\test>if 10 == 4 goto SET30

C:\Documents and Settings\jdw\Desktop\test>if 10 == 5 goto SET31

C:\Documents and Settings\jdw\Desktop\test>if 10 == 6 goto SET30

C:\Documents and Settings\jdw\Desktop\test>if 10 == 7 goto SET31

C:\Documents and Settings\jdw\Desktop\test>if 10 == 8 goto SET31

C:\Documents and Settings\jdw\Desktop\test>if 10 == 9 goto SET30

C:\Documents and Settings\jdw\Desktop\test>if 10 == 10 goto SET31

C:\Documents and Settings\jdw\Desktop\test>set /A dd=31 + -18

C:\Documents and Settings\jdw\Desktop\test>goto LoopDate

C:\Documents and Settings\jdw\Desktop\test>IF /I 13 GTR 0 (GOTO DONE )

C:\Documents and Settings\jdw\Desktop\test>IF 13 LSS 10 set dd=013

C:\Documents and Settings\jdw\Desktop\test>IF 10 LSS 10 set mm=010

C:\Documents and Settings\jdw\Desktop\test>for /F "delims=" %i in ('dir /s /b /a
-d 2>NUL') do (
set FileName=%i
 SET FTIME=%~ti
 CALL :PROCESSFILE
)

C:\Documents and Settings\jdw\Desktop\test>(
set FileName=C:\Documents and Settings\jdw\Desktop\test\082604.txt
 SET FTIME=08/26/2004 06:27 AM
 CALL :PROCESSFILE
)

C:\Documents and Settings\jdw\Desktop\test>set fyyyy=2004

C:\Documents and Settings\jdw\Desktop\test>set fmm=08

C:\Documents and Settings\jdw\Desktop\test>set fdd=26

C:\Documents and Settings\jdw\Desktop\test>if /I 2004 GTR 2069 set fyyyy=1920

C:\Documents and Settings\jdw\Desktop\test>echo if /I 20041013 GEQ 20040826 (
if /I 20041013 GEQ 20040826 (

C:\Documents and Settings\jdw\Desktop\test>DEL "C:\Documents and Settings\jdw\De
sktop\test\082604.txt"

C:\Documents and Settings\jdw\Desktop\test>ECHO Delete C:\Documents and Settings
\jdw\Desktop\test\082604.txt
Delete C:\Documents and Settings\jdw\Desktop\test\082604.txt

C:\Documents and Settings\jdw\Desktop\test>PAUSE
Press any key to continue . . .

Dan
0
 
LVL 2

Author Comment

by:whiting002
ID: 12565359
Steve,

I got it working thanks so much for the help.  I do have one more question for you, I'm familiar with programming in VB and C but I've never done much with scripts.  Can you help me by commenting out some of this code for me so I can see exactly what everything is doing?  I'm a little confused for instance with "FOR /F "TOKENS=2-4 DELIMS=/ " %%F IN ('DATE /T') DO (", I realize this is a for statement but what is the '/F' and what is the '=/".  Also what does the '%' mean in a script.  Another question is the '/I' and the '/A' that are in the code, what are these.  Arrays maybe?  If you can help take me through this code I'll throw in an extra 100 points.  If you don't feel like it that fine to I'll still award you the 250 but I would like to learn a little bit about the batch scripting.


:: ---------------EXAMPLE.BAT-----------------
@ECHO OFF
:: ------------
:: This is where you set the number
:: of minutes you want subtracted
:: from the current date/time.
:: ------------
cd C:\Documents and Settings\jdw\Desktop\test
SET MyDays=30


:: ------------
:: Get current date/time
:: ------------
FOR /F "TOKENS=2-4 DELIMS=/ " %%F IN ('DATE /T') DO (
 SET YYYY=%%H
 SET MM=%%F
 SET DD=%%G
)

IF %DD% LSS 10 (SET DD=%DD:~1%)
IF %MM% LSS 10 (SET MM=%MM:~1%)

: ------------
:: Subtract days from current date.
:: ------------
SET /A DD=%DD% - %MyDays%

:: ------------
:: Do the massively painful
:: reverse calculations.. :(
:: ------------
:LoopDate
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 LoopDate
:SET30
set /A dd=30 + %dd%
goto LoopDate
: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 LoopDate
:SET29
set /A dd=29 + %dd%
goto LoopDate
:DONE
IF %dd% LSS 10 set dd=0%dd%
IF %mm% LSS 10 set mm=0%mm%

::for %%i in (*.*) do (
for /f "delims=" %%i in ('dir /s /b /a-d 2^>NUL') do (
 set FileName=%%i
 SET FTIME=%%~ti
 CALL :PROCESSFILE
)

set mm=
set yyyy=
set dd=
set thedate=
goto :EOF

:PROCESSFILE
set fyyyy=%FTIME:~6,4%
set fmm=%FTIME:~0,2%
set fdd=%FTIME:~3,2%

if /I %fyyyy% GTR 2069 set fyyyy=19%FTIME:~6,2%

:: +*************************************+
:: | 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% (
  DEL "%FileName%"
  ECHO Delete %FileName%
)
ECHO Cacldate=%yyyy%%mm%%dd%

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

:EXIT
:: ----------END-EXAMPLE.BAT-------------
0
 
LVL 30

Expert Comment

by:SteveGTR
ID: 12566242
No problem. First help is available for all the commands by typing command /? at the DOS prompt (example: if /?).

The for statement has been improved greatly. I'll breakdown the following:

FOR /F "TOKENS=2-4 DELIMS=/ " %%F IN ('DATE /T') DO (

The /F reads the file our output from the command in the (). In this case we have 'date /t'. The /t parameter of date just outputs the date:

Fri 11/12/2004

The delims option tells the for how to breakup the line items. The default is a space, but in this case we are using the date slash and a space. So the for statement will breakup the output from date into 4 tokens: Fri, 11, 12, 2004.

The tokens options says we want the 2nd through 4th token. This skips the day of week and extracts the 11, 12, and 2004. The %%f  is the variable for the 1st token, %%g for the 2nd, and %%h for the 3rd. If we used %%a then the tokens would be distributed from %%a to %%c. In our usage here is what the values would equate to:

%%f = 11
%%g = 12
%%h = 2004

The /I option is used for the if statement. It says to use case insensitive string compares. So "a" is equal to "A".

The /A option of the set statement allows you to activate numeric processing. For example:

set /a n=2 * 10
echo n=%n%

Would output 20.

The only thing you have to watch out for with set /a is octal numbers. This happens alot when parsing dates because of the leading zeros. I get around this by doing the following.

set mm=09
set /a mm=1%mm% - 100

This strips the leading zero by saying 109 - 100 = 9. If you didn't do this the next time you tried to use mm to say add 1 to the month you'd receive an error - invalid octal number.

I hope that helps :)
0
 
LVL 2

Author Comment

by:whiting002
ID: 12566680
Steve,

Thanks a lot I really appreciate it.

Dan Whiting
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

One of my most closely kept secrets is revealed in this discussion How to output text on the same line This question was recently posted in EE by Simon336697 (http://www.experts-exchange.com/Programming/Languages/Scripting/Shell/Batch/Q_2459…
Being a system administrator some time we require to do things remotely, one of them is installing software. Here I am going to tell you how to install software through wmic (Windows management instrument console). I am not at all saying that this i…
Screencast - Getting to Know the Pipeline
How can you see what you are working on when you want to see it while you to save a copy? Add a "Save As" icon to the Quick Access Toolbar, or QAT. That way, when you save a copy of a query, form, report, or other object you are modifying, you…

577 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question