# Solved: Deleting Folders older than 30 days from date.



## scrfix (May 3, 2009)

I would like to try to write this on my own however need a push in the correct direction.

I have TB drive where I save the data for my clients for 30 days. I am currently manually going there and anything over 30 days I am removing the directory.

I know how to look at the directory names with a FOR statement. How would I match their dates with the current date?

The OS is 2003 Small Business Server if that matters.


----------



## Freemorrison (Nov 29, 2009)

So basically you would like to have an app that will sweep out any - and all files older than 30 days on your TB- is that correct?


----------



## scrfix (May 3, 2009)

Yes.

However I would like to write this in Batch. I don't mind using an application in the meantime however my goal is to sharpen my BAT skills so I am attempting to write most of the stuff I do in Batch for the time being until such time as I go onto the next language.

It would be the directories and subdirectories I would be deleting however.

RD ?? /S /Q


----------



## Freemorrison (Nov 29, 2009)

Hmm,,, see if this is similar to what you need?
http://www.lazynetworkadmin.com/knowledgebase-mainmenu-6/2-windows/76-ftp-cleanup-script

For a Mac
http://www.macosxhints.com/article.php?story=20060831174513296


----------



## scrfix (May 3, 2009)

Not quite what i am looking for but does help push me in the right direction. 

I now now that I have to get todays date probably from date. Just have to figure out how to compare the created date of the folder against todays date.


----------



## scrfix (May 3, 2009)

Okay,

I have a portion of this written


```
FOR /F "tokens=1-4 delims=/ " %%I IN ('DATE /t') DO SET /A mydate=%%J%%K%%L
 
FOR /F tokens=1 %%A IN ('DIR /t:C') DO CALL :_removedirs "%%A"
:_removedirs
if [%1]< GOTO :EOF
GOTO :EOF
```
Am I heading in the right direction or am I way off base? I am running into errors with the /A without the delims=/ because it keeps wanting to divide. I was thinking of coming up with an alogrithm that turned the date to number and then subtracted 30 or something but I figure there has to be an easier way, right?


----------



## TheOutcaste (Aug 8, 2007)

Here's an outline:


 Determine system's regional settings to determine date format.
 Get today's date
 Convert to Julian so you can do date math easily
 Subtract the number of days you want to keep to get a Julian date to compare to.
 Get list of files or folders, convert the flle/folder dates to Julian
 Compare with the target date and delete file/remove folder if older.

Some things to look out for.
A folder's modified date doesn't always get updated when a file in the folder gets modified, it can take up to an hour for the changed date to be written to disk and appear in explorer or the command prompt.
If this is an Archive where once the folder is created, files in the folders won't be updated, added, or changed it won't matter.
If files can be updated, added, or changed, there's a 1 hour window where a file could have been changed, but the folder date won't show it, and you could delete the entire folder by mistake if you look only at folder dates.
In that case you'd want to check the dates of each file, remove if they meet the criteria, then if the folder is empty, remove the folder.

The *%~t* modifier shows the modified date, not the created date. If you need to check the created date, you can't use a bare Dir listing. You'd need to parse the full dir output to extract the date.

*Dir /OD* will sort by date, you can jump out of the loop when the dates get new enough.
*Dir /OD /S* sorts by date within each folder, so you can't jump out.

If you are only looking at one level of folders it's pretty easy, if you need to search through a tree, it gets complex.

You can walk the tree and check files in each folder, or might work to output date and full name for each file in the tree to a file (Echo Juliandate:fullpath), use sort to sort by date, then read the file, check date, and delete until the dates reach the taget date.

I think you probably have the date routines to get the date and convert to julian. I updated the getdate routine a couple weeks ago when Squashman pointed out it doesn't work if the system uses a two digit year setting. The new version is in Post 8 in this thread:
http://forums.techguy.org/software-development/885945-solved-missing-operator-batch-script.html


----------



## scrfix (May 3, 2009)

Actually I did not know about the Julian Date. I have utilized dates in the past but not to compare, only to write log files. This one is new for me.

I am reading over your post now.

I wrote some FOR statements above. The time one I actualy copied from somewhere however it was almost what I had with the exception of the delims=/


----------



## scrfix (May 3, 2009)

Okay I have found a subroutine which teaches me how and actually has examples on how to convert to a Julian Date.
http://www.robvanderwoude.com/datetimentmath.php


----------



## scrfix (May 3, 2009)

Thanks, I will look into this tomorrow. I am getting extremely tired. Need some sleep. 2:34am here.


----------



## TheOutcaste (Aug 8, 2007)

Yeah we hit send at about the same time.
You don't need the /A with the Set statement, you're not doing math in that particular line, just getting the date into variable without the nonnumeric delimiters (/)
You can also just extract substrings from %date%, but it only works if the format is the same.
if you figure on MM/DD/YYYY and it's YYYY/MM/DD or DD/MM/YYYY you can have "issues"
If it's US format (MM/DD/YYYY) this will work, doesn't car if the day of the week is included:
%Date:~-4,4% will give the year
%Date:~-7,2% will give the day
%Date:~-10,2% will give the month
If you run this on the first of the month, you can just compare the months with a little adjustment and delete only those items with a month older than last month
If month <3 add 12 and subtract 1 from year
combine the new numbers as YYYYMM, so Jan2009 would end up 200813. Now subtract 1 to get 200812
Get year and month for each file, if <200812 delete.
Feb would be 200813
March would be 200902
Not exactly 30, deletes items over 1 month (28-31 days) old.
If you need it to be exactly 30 days no matter when you run it, best to convert to Julian.


----------



## Freemorrison (Nov 29, 2009)

This might also work?
http://cyber-d.blogspot.com/2005/10/cyber-ds-auto-delete-101.html


----------



## scrfix (May 3, 2009)

FreeMorrison,

That is actually a great looking tool. I will see if it works on Server 2003 software.

I am still going to write the Bat file however. The goal here is to attempt to sharpen my Batch writing skills. In the meantime, I will utilize that software if it runs.

Thanks,

Jerry,

Thanks for the heads up. I don't need it to be exact. Just 1 month is all. We tell clients that we keep their data for 1 month before it gets deleted. I am going to attempt to write a script with what you have provided.


----------



## scrfix (May 3, 2009)

Okay,

That page I posted above. Nevermind about that. It doesn't work. It was written for NT nd is not compatible with XP, Vista, etc. However I did simply rewrite my own based upon the same algorithm that the original write wrote his.

However my question is this:
How do I know what the correct Julian date really is?
Let me explain:

According to this military website the Julian date is one date: http://aa.usno.navy.mil/data/docs/JulianDate.php

However according to the original site above:
http://www.robvanderwoude.com/datetimentmath.php

As well as this website
http://www.fourmilab.ch/documents/calendar/

I am presuming that this means that the military website is wrong??

Here is my code:

```
echo off
FOR /F "tokens=1-4 delims=/ " %%I IN ('DATE /t:C') DO (
SET _mth=%%J
SET _day=%%K
SET _yr=%%L
)
Echo Converting Real Date to Julian Date
SET /A _month=((%_mth%-14)/12)
SET /A _year=(%_yr%+4800)
Echo _month= %_month%
Echo _year = %_year%
SET /A _jdate=((1461*(%_year%+%_month%)/4)+((367*((%_mth%-2)-(12*%_month%)))/12))-((3*((%_year%+%_month%+100)/100))/4)+(%_day%-32075)
Echo %_jdate%
GOTO:EOF
```
Here is the new julian date algorithm that will allow calculating between two dates.

Given credit where credit is due.

Date: 05/29/2003 at 08:39:20
From: Doctor Fenton
Subject: Re: Fliegel-Van Flandern algorithm

The algorithm I utilized to convert this is from
Given Y,M,D, the year, month, and date, define (using integer 
arithmetic)

M1 = (M-14)/12
Y1 = Y + 4800 .

Then the Julian date J is

J = 1461*(Y1+M1)/4 + 367*(M-2-12*M1)/12 - (3*((Y1+M1+100)/100))/4
+ D - 32075 .

For example, for Y = 2001, M = 2, and D = 24,

M1 = -1 
Y1 = 6801 ,

and

J = 2483700 + 367 - 51 + 24 -32075

= 2451965 .

These algorithms are available in the Explanatory Supplement to the
Astronomical Almanac, 2nd edition, P. Seidelmann (ed.), or in 
Fliegel and Van Flandern's original paper,

Fliegel, H. F., and Van Flandern, T. C., "A Machine Algorithm for
Processing Calendar Dates," Communications of the Association of
Computing Machines, vol. 11 (1968), p. 657.

If you have any questions, please write back and I will try to 
explain further.

- Doctor Fenton, The Math Forum
http://mathforum.org/dr.math/

Okay, so now I can convert over to a Julian Date. That was actually pretty simple. I thought that was going to be a lot harder.

Tell me if I am heading in the correct direction.

Next step.
Get the CREATED date from each one of the directories in a FOR statement as described above.

DIR /t:C

Something to the below other than I have to point it to what directory and figure out the math.


```
FOR /F tokens=1 %%A IN ('DIR /t:C') DO CALL :_removedirs "%%A"
 
:_removedirs
:: SET /A _createdate= (or should this be in the FOR statement, probably)
:: if [%1]< GOTO :EOF
:: GOTO :EOF
```


----------



## Squashman (Apr 4, 2003)

This sounds like a good time to use forfiles.


----------



## scrfix (May 3, 2009)

Isn't that just for files? I am attempting to remove the whole directory and all files and subdirectories within it. I do like the feature in forfiles /D for the date. That is nice however I am wondering if it would be just for those files within the directories and not the directories themselves. If so, then RD would be better would it not?


----------



## TheOutcaste (Aug 8, 2007)

The military uses an Ordinal date that they incorrectly refer to as a Julian date.
Today, Jan 10, 2010
Ordinal = 2010-010 aka Julian in the military
Julian = 2455207

Had a thread about that just a while ago here:
http://forums.techguy.org/software-development/885945-solved-missing-operator-batch-script.html

Spoiler alert: The above thread includes the same jdate routine from Rob's site, modified a bit so it won't crash if passed single digit months or days, plus my Getdate routine (also modified from a script on Rob's page) to check regional settings and return the date in a standard format regardless of regional settings.

Headed the right way.
No real need to call a subroutine, but it does help to break it down into smaller steps.
You'll want to sort the Dir output by date, not just specify the date to use, and skip the header lines. Remember a system may have the Dir sort order specified in the *dircmd* variable, so you can't depend on the defaults.

Forfiles would be great, but I don't think you can set it to use the created date, it only returns the modified date. Though for this usage that should work as well. It isn't available on XP though, but can be downloaded from here and is included with the Windows 2000 Resource kit. The Server 2003 version works on XP as well.

It will work with directories as well; after all, a directory is just a file with the directory attribute set. In the command you just test for @isdir=TRUE then check the date and do a RD if it meets the criteria to be deleted.


----------



## scrfix (May 3, 2009)

I am having an issue.

I have the FOR statement written for testing. There are 10 directories in the directory I am testing.


```
FOR /F "tokens=1" %%I IN ('dir /AD /OD /T:C') DO Echo %%I
```
The results for the above code:

Volume
Volume
Directory
04/12/2009
04/12/2009
05/02/2009
05/14/2009
05/17/2009
06/25/2009
08/24/2009
09/26/2009
12/23/2009
01/07/2010
01/08/2010
01/08/2010
0
12

*Questions*

The above code pulls up 16 results. I understand that a portion of this is header information such as the volume volume and directory. I attempted to utilize the /B and then no dates come up.

I understand that the 0 and 12 are 0 files and 12 directories listed in the summary.

1. I am presuming it is looking at . and .. as well and that is why it is outputting 12 dates instead of 10.

2. I have used:
"tokens=1-4 delims=/ " 
"tokens=1-4 delims=/ "
"tokens=1 delims=/"
"tokens=1 delims=/ "
"tokens=1,2,3 delims=/ "
"tokens=1,2,3 delims=/"
and many other variants and all that it retuns no matter how many tokens I put in or how I put them in except for 1 is:
Volume in drive C is OS
Volume Serial Number is 1A72-64AD
Directory of C:\testbats
04
04
05
05
05
06
08
09
12
01
01
01
0 File(s) 0 bytes
12 Dir(s) 47,854,628,864 bytes free

I am attempting to get it to return just:
a) The 10 directory dates without header and summary information
b) No . or .. information first

05022009
05142009
05172009
06252009
08242009
09262009
12232009
01072010
01082010
01082010

What am I doing wrong?


----------



## TheOutcaste (Aug 8, 2007)

Skip the first 4 lines to remove the header.
Should add the *-L* switch so Junction points aren't included, just in case. (I'm testing on Win 7 so might not apply for you)
You can pipe it to Findstr to remove the . and .. entries, but that will remove any entry with a period. Findstr will work for *File(s)* and *Dir(s)* unless you have a folder with either of those strings with the exact same case in the name.

. and .. _should_ be the first two entries, so *skip=7 *will bypass them, but it is possible to move a folder into the tree that would have an earlier creation date.
This will work if they are always the first two (also displays the Dir name just for testing):

```
For /F "Tokens=1,4* skip=7" %%I In ('Dir /AD-L /OD /TC^|Findstr /L /V "File(s) Dir(s)"') Do Echo %%I - %%K
```
Safest to check the Dir name to skip . and ..
Also get the 2nd token and check if it's *File(s)* or *Dir(s)*. The 2nd token will be the time for any folder.
You could also check the 4th token (%%K) to see if it's <JUNCTION> to avoid issues with the *-L* attribute not being recognized, but it should be ignored. XP Home ignores it.
Something like this:

```
For /F "Tokens=1,2,4* skip=4" %%I In ('Dir /AD-L /OD /TC') Do If Not %%L==. If Not %%L==.. If Not "%%J"=="File(s)" If Not "%%J"=="Dir(s)" Echo %%I - %%L
```
The double quotes are needed so the (s) doesn't confuse things. Or you have to excape the ( and )


----------



## scrfix (May 3, 2009)

Thanks for pointing that out.

1. I am not sure why you have to skip 7. I see that it works and is correct however there are only 5 lines.

2. I am having some issues. I was attempting to set a variable = %%I and a different variable = %%K and I keep getting errors. I also attempted to put the If statements ....hmmmm I think I just answered my own questions. I need to enable delayed expansion and it should work. Nevermind on that one. I will try it tomorrow after I get back from work.

The first question I still need an answer for.


----------



## scrfix (May 3, 2009)

Here is what I have thus far:

Am I completely way off base here OR am I heading in the right direction and just screwed up. Currently the script has an error on it. Going to bed. I am too tired to troubleshoot.

I have not gotten to the point of doing the subtraction yet. I am merely attempting to get the first directory into %_jdate%


```
echo off
SET _dt=DATE /t
SET _count=1
 
:_JDateConversion
FOR /F "tokens=1-4 delims=/ " %%I IN ('%_dt%') DO (
SET _mth=%%J
SET _day=%%K
SET _yr=%%L
)
SET /A _month=((%_mth%-14)/12)
SET /A _year=(%_yr%+4800)
SET /A _jdate=((1461*(%_year%+%_month%)/4)+((367*((%_mth%-2)-(12*%_month%)))/12))-((3*((%_year%+%_month%+100)/100))/4)+(%_day%-32075)
IF %_count%==1 GOTO _StoreCurrentJulianDate
IF NOT %_count%==1 GOTO :EOF
 
:_StoreCurrentJulianDate
SET _currentjdate=%_jdate%
SET _jdate=
SETLocal EnableDelayedExpansion
For /F "Tokens=1,4* skip=7" %%I In ('Dir /AD-L /OD /TC^|Findstr /L /V "File(s) Dir(s)"') Do (
SET _dt=%%I
SET _dirname=%%K
SET _dt=!_dt:/=!
CALL :_JDateConversion !_dt!
Echo %_jdate%
echo !_dt! - !_dirname!
)
 
:: FOR /F "tokens=1 skip=7" %%I IN ('dir /AD-L /OD /T:C') DO Echo %%I
:: For /F "Tokens=1,2,4* skip=4" %%I In ('Dir /AD-L /OD /TC') Do If Not %%L==. If Not %%L==.. If Not "%%J"=="File(s)" If Not "%%J"=="Dir(s)" SET _dirdate=%%I SET _dirname=%%L SET _dirdate=%_dirdate:/=% echo %_dirname%
SETLocal DisableDelayedExpansion
GOTO :EOF
```


----------



## TheOutcaste (Aug 8, 2007)

scrfix said:


> 1. I am not sure why you have to skip 7. I see that it works and is correct however there are only 5 lines.




```
Line 1 -  Volume in drive C is Windows 7
Line 2 -  Volume Serial Number is 1851-EA9C
Line 3 - 
Line 4 -  Directory of C:\Temp Dir
Line 5 - 
Line 6 - 01/13/2010  12:18 AM    <DIR>          .
Line 7 - 01/13/2010  12:18 AM    <DIR>          ..
```
A quick look at the code shows
Start of subroutine
get jdate for today
save it
do For loop with dir -- this is part of the jdate routine, you never exited it
call routine -- you are still in the routine you are calling

Put the routine at the end, or jump around it, then call it for all dates.

Need something like this:
Initialize variables
get current date - Call jdate routine - save returned date

Dir in a for loop to get date; for each, call jdate routine - check date, skip if too new


----------



## scrfix (May 3, 2009)

Okay,

I am finally able to get back to this for a few minutes before I have to get into the attic to get some cables ran.

There is an error happening and I think I know why but not sure how to fix it.

Here is the code. Keep in mind there is a _count in there. I forget what I was going to utilize that for. I think it was supposed to be utilized for counting the number of directories and then when it got to 0 then it exited the program however I haven't gotten that far with it yet.


```
echo on
:: initalize variables
SET _dt=DATE /t
SET _count=1
:_JDateConversion
FOR /F "tokens=1-4 delims=/ " %%I IN ('%_dt%') DO (
SET _mth=%%J
SET _day=%%K
SET _yr=%%L
)
SET /A _month=((%_mth%-14)/12)
SET /A _year=(%_yr%+4800)
SET /A _jdate=((1461*(%_year%+%_month%)/4)+((367*((%_mth%-2)-(12*%_month%)))/12))-((3*((%_year%+%_month%+100)/100))/4)+(%_day%-32075)
IF %_count%==1 CALL :_StoreCurrentJulianDate
IF NOT %_count%==1 GOTO :EOF
set _count=
GOTO _GetDirDates
:_StoreCurrentJulianDate
SET _currentjdate=%_jdate%
SET _jdate=
GOTO :EOF
:_GetDirDates
SETLocal EnableDelayedExpansion
For /F "Tokens=1,4* skip=7" %%I In ('Dir /AD-L /OD /TC^|Findstr /L /V "File(s) Dir(s)"') Do (
SET _dt=%%I
SET _dirname=%%K
CALL :_JDateConversion !_dt!
Echo %_jdate%
echo !_dt! - !_dirname!
)
:: FOR /F "tokens=1 skip=7" %%I IN ('dir /AD-L /OD /T:C') DO Echo %%I
:: For /F "Tokens=1,2,4* skip=4" %%I In ('Dir /AD-L /OD /TC') Do If Not %%L==. If Not %%L==.. If Not "%%J"=="File(s)" If Not "%%J"=="Dir(s)" SET _dirdate=%%I SET _dirname=%%L SET _dirdate=%_dirdate:/=% echo %_dirname%
SETLocal DisableDelayedExpansion
GOTO :EOF
```
Here is the results with the error.


```
C:\test scripts>datecalc.bat
C:\test scripts>echo on
C:\test scripts>SET _dt=DATE /t
C:\test scripts>SET _count=1
C:\test scripts>FOR /F "tokens=1-4 delims=/ " %I IN ('DATE /t') DO (
SET _mth=%J
 SET _day=%K
 SET _yr=%L
)
C:\test scripts>(
SET _mth=01
 SET _day=24
 SET _yr=2010
)
C:\test scripts>SET /A _month=((01-14)/12)
C:\test scripts>SET /A _year=(2010+4800)
C:\test scripts>SET /A _jdate=((1461*(6810+-1)/4)+((367*((01-2)-(12*-1)))/12))-((3*((6810+-1+100)/100))/4)
+(24-32075)
C:\test scripts>IF 1 == 1 CALL :_StoreCurrentJulianDate
C:\test scripts>SET _currentjdate=2455221
C:\test scripts>SET _jdate=
C:\test scripts>GOTO :EOF
C:\test scripts>IF NOT 1 == 1 GOTO :EOF
C:\test scripts>set _count=
C:\test scripts>GOTO _GetDirDates
C:\test scripts>SETLocal EnableDelayedExpansion
C:\test scripts>For /F "Tokens=1,4* skip=7" %I In ('Dir /AD-L /OD /TC|Findstr /L /V "File(s) Dir(s)"') Do
(
SET _dt=%I
 SET _dirname=%K
 CALL :_JDateConversion !_dt!
 Echo
 echo !_dt! - !_dirname!
)
C:\test scripts>(
SET _dt=05/02/2009
 SET _dirname=file test
 CALL :_JDateConversion !_dt!
 Echo
 echo !_dt! - !_dirname!
)
C:\test scripts>FOR /F "tokens=1-4 delims=/ " %I IN ('05/02/2009') DO (
SET _mth=%J
 SET _day=%K
 SET _yr=%L
)
'05' is not recognized as an internal or external command,
operable program or batch file.
```
The issue here is that the DATE /t works perfectly in that CALL however when I get the date from the directories then I get an error stating that 05 is not a valid function. I think this is because of the EnabledDelayedExpansion however if I don't turn it on then it doesn't work at all.

Not sure what to do at this point with the exception of rewrite a different way. Suggestions?

I added a couple of the suggestions with the outs for the code. Didn't get to the other ones.


----------



## TheOutcaste (Aug 8, 2007)

The For loop is expecting a Command. The first time it sees *Date /T*
When called as a subroutine, it's trying to execute the date that the *_dt* variable contains as a Command, and 05 (May) is not a command.
Note there is no need to pass the variable on the Call line as you never reference %1 in the routine.

This should work for this usage:

```
SET _dt=[COLOR=Red]Echo.[/COLOR]%%I
SET _dirname=%%K
CALL :_JDateConversion
Echo %_jdate%
```


----------



## scrfix (May 3, 2009)

Okay,

Thanks. I didn't even think of that. It is the /F in the FOR statement telling it to do the command and read the results.

*Updated Note: 1:17am EST*
I have already resolved this issue. I know why the error is coming up and have a resolution for it.

I have a different issue happening. I figured out the issue with the CALL statement and some other things. I actually have this working to a point. There are some errors that I don't know why they are happening.

*Code*

```
echo on
:: initalize variables
SET _dt=DATE /t
SET _count=1
CALL :_JDateConversion
:_JDateConversion
FOR /F "tokens=1-4 delims=/ " %%I IN ('%_dt%') DO (
SET _mth=%%J
SET _day=%%K
SET _yr=%%L
)
SET /A _month=((%_mth%-14)/12)
SET /A _year=(%_yr%+4800)
SET /A _jdate=((1461*(%_year%+%_month%)/4)+((367*((%_mth%-2)-(12*%_month%)))/12))-((3*((%_year%+%_month%+100)/100))/4)+(%_day%-32075)
SET _mth=
SET _day=
SET _yr=
SET _month=
SET _year=
IF NOT %_count%==1 GOTO :EOF
IF %_count%==1 (
CALL :_StoreCurrentJulianDate
)
set /A _count=0
GOTO _GetDirDates
:_StoreCurrentJulianDate
SET _currentjdate=%_jdate%
SET _jdate=
GOTO :EOF
:_GetDirDates
SETLocal EnableDelayedExpansion
For /F "Tokens=1,4* skip=7" %%I In ('Dir /AD-L /OD /TC^|Findstr /L /V "File(s) Dir(s)"') Do (
SET _dt=Echo.skip %%I
SET _dirname=%%K
CALL :_JDateConversion
Echo _jdate=!_jdate!
echo Date=!_dt! - Directory=!_dirname!
)
:: FOR /F "tokens=1 skip=7" %%I IN ('dir /AD-L /OD /T:C') DO Echo %%I
:: For /F "Tokens=1,2,4* skip=4" %%I In ('Dir /AD-L /OD /TC') Do If Not %%L==. If Not %%L==.. If Not "%%J"=="File(s)" If Not "%%J"=="Dir(s)" SET _dirdate=%%I SET _dirname=%%L SET _dirdate=%_dirdate:/=% echo %_dirname%
SETLocal DisableDelayedExpansion
GOTO :EOF
```
*Partial output for Errors*

```
C:\test scripts>SET _month=
C:\test scripts>SET _year=
C:\test scripts>IF NOT 0 == 1 GOTO :EOF
_jdate=2455008
Date=Echo.skip 06/25/2009 - Directory=testing
C:\test scripts>(
SET _dt=Echo.skip 08/24/2009
 SET _dirname=Mirror Yes
 CALL :_JDateConversion
 Echo _jdate=!_jdate!
 echo Date=!_dt! - Directory=!_dirname!
)
C:\test scripts>FOR /F "tokens=1-4 delims=/ " %I IN ('Echo.skip 08/24/2009') DO (
SET _mth=%J
 SET _day=%K
 SET _yr=%L
)
C:\test scripts>(
SET _mth=08
 SET _day=24
 SET _yr=2009
)
C:\test scripts>SET /A _month=((08-14)/12)
Invalid number.  Numeric constants are either decimal (17),
hexadecimal (0x11), or octal (021).
C:\test scripts>SET /A _year=(2009+4800)
C:\test scripts>SET /A _jdate=((1461*(6809+)/4)+((367*((08-2)-(12*)))/12))-((3*((6809++100)/100))/4)+(24-3
2075)
Missing operand.
C:\test scripts>SET _mth=
C:\test scripts>SET _day=
C:\test scripts>SET _yr=
C:\test scripts>SET _month=
C:\test scripts>SET _year=
C:\test scripts>IF NOT 0 == 1 GOTO :EOF
_jdate=2455008
Date=Echo.skip 08/24/2009 - Directory=Mirror Yes
C:\test scripts>(
SET _dt=Echo.skip 09/26/2009
 SET _dirname=Chantilly Homes
 CALL :_JDateConversion
 Echo _jdate=!_jdate!
 echo Date=!_dt! - Directory=!_dirname!
)
C:\test scripts>FOR /F "tokens=1-4 delims=/ " %I IN ('Echo.skip 09/26/2009') DO (
SET _mth=%J
 SET _day=%K
 SET _yr=%L
)
C:\test scripts>(
SET _mth=09
 SET _day=26
 SET _yr=2009
)
C:\test scripts>SET /A _month=((09-14)/12)
Invalid number.  Numeric constants are either decimal (17),
hexadecimal (0x11), or octal (021).
C:\test scripts>SET /A _year=(2009+4800)
C:\test scripts>SET /A _jdate=((1461*(6809+)/4)+((367*((09-2)-(12*)))/12))-((3*((6809++100)/100))/4)+(26-3
2075)
Missing operand.
C:\test scripts>SET _mth=
C:\test scripts>SET _day=
C:\test scripts>SET _yr=
C:\test scripts>SET _month=
C:\test scripts>SET _year=
C:\test scripts>IF NOT 0 == 1 GOTO :EOF
_jdate=2455008
Date=Echo.skip 09/26/2009 - Directory=Chantilly Homes
C:\test scripts>(
SET _dt=Echo.skip 12/23/2009
 SET _dirname=Walker
 CALL :_JDateConversion
 Echo _jdate=!_jdate!
 echo Date=!_dt! - Directory=!_dirname!
)
C:\test scripts>FOR /F "tokens=1-4 delims=/ " %I IN ('Echo.skip 12/23/2009') DO (
SET _mth=%J
 SET _day=%K
 SET _yr=%L
)
C:\test scripts>(
SET _mth=12
 SET _day=23
 SET _yr=2009
)
C:\test scripts>SET /A _month=((12-14)/12)
C:\test scripts>SET /A _year=(2009+4800)
C:\test scripts>SET /A _jdate=((1461*(6809+0)/4)+((367*((12-2)-(12*0)))/12))-((3*((6809+0+100)/100))/4)+(2
3-32075)
C:\test scripts>SET _mth=
C:\test scripts>SET _day=
C:\test scripts>SET _yr=
C:\test scripts>SET _month=
C:\test scripts>SET _year=
C:\test scripts>IF NOT 0 == 1 GOTO :EOF
_jdate=2455189
Date=Echo.skip 12/23/2009 - Directory=Walker
C:\test scripts>(
SET _dt=Echo.skip 01/07/2010
 SET _dirname=runonly
 CALL :_JDateConversion
 Echo _jdate=!_jdate!
 echo Date=!_dt! - Directory=!_dirname!
)
C:\test scripts>FOR /F "tokens=1-4 delims=/ " %I IN ('Echo.skip 01/07/2010') DO (
SET _mth=%J
 SET _day=%K
 SET _yr=%L
)
C:\test scripts>(
SET _mth=01
 SET _day=07
 SET _yr=2010
)
C:\test scripts>SET /A _month=((01-14)/12)
C:\test scripts>SET /A _year=(2010+4800)
C:\test scripts>SET /A _jdate=((1461*(6810+-1)/4)+((367*((01-2)-(12*-1)))/12))-((3*((6810+-1+100)/100))/4)
+(07-32075)
C:\test scripts>SET _mth=
C:\test scripts>SET _day=
C:\test scripts>SET _yr=
C:\test scripts>SET _month=
C:\test scripts>SET _year=
C:\test scripts>IF NOT 0 == 1 GOTO :EOF
_jdate=2455204
Date=Echo.skip 01/07/2010 - Directory=runonly
C:\test scripts>(
SET _dt=Echo.skip 01/08/2010
 SET _dirname=01-06-10
 CALL :_JDateConversion
 Echo _jdate=!_jdate!
 echo Date=!_dt! - Directory=!_dirname!
)
C:\test scripts>FOR /F "tokens=1-4 delims=/ " %I IN ('Echo.skip 01/08/2010') DO (
SET _mth=%J
 SET _day=%K
 SET _yr=%L
)
C:\test scripts>(
SET _mth=01
 SET _day=08
 SET _yr=2010
)
C:\test scripts>SET /A _month=((01-14)/12)
C:\test scripts>SET /A _year=(2010+4800)
C:\test scripts>SET /A _jdate=((1461*(6810+-1)/4)+((367*((01-2)-(12*-1)))/12))-((3*((6810+-1+100)/100))/4)
+(08-32075)
Invalid number.  Numeric constants are either decimal (17),
hexadecimal (0x11), or octal (021).
C:\test scripts>SET _mth=
C:\test scripts>SET _day=
C:\test scripts>SET _yr=
C:\test scripts>SET _month=
C:\test scripts>SET _year=
C:\test scripts>IF NOT 0 == 1 GOTO :EOF
_jdate=2455204
Date=Echo.skip 01/08/2010 - Directory=01-06-10
C:\test scripts>(
SET _dt=Echo.skip 01/08/2010
 SET _dirname=Old Stuff
 CALL :_JDateConversion
 Echo _jdate=!_jdate!
 echo Date=!_dt! - Directory=!_dirname!
)
C:\test scripts>FOR /F "tokens=1-4 delims=/ " %I IN ('Echo.skip 01/08/2010') DO (
SET _mth=%J
 SET _day=%K
 SET _yr=%L
)
C:\test scripts>(
SET _mth=01
 SET _day=08
 SET _yr=2010
)
C:\test scripts>SET /A _month=((01-14)/12)
C:\test scripts>SET /A _year=(2010+4800)
C:\test scripts>SET /A _jdate=((1461*(6810+-1)/4)+((367*((01-2)-(12*-1)))/12))-((3*((6810+-1+100)/100))/4)
+(08-32075)
Invalid number.  Numeric constants are either decimal (17),
hexadecimal (0x11), or octal (021).
C:\test scripts>SET _mth=
C:\test scripts>SET _day=
C:\test scripts>SET _yr=
C:\test scripts>SET _month=
C:\test scripts>SET _year=
C:\test scripts>IF NOT 0 == 1 GOTO :EOF
_jdate=2455204
Date=Echo.skip 01/08/2010 - Directory=Old Stuff
C:\test scripts>SETLocal DisableDelayedExpansion
C:\test scripts>GOTO :EOF
C:\test scripts>FOR /F "tokens=1-4 delims=/ " %I IN ('DATE /t') DO (
SET _mth=%J
 SET _day=%K
 SET _yr=%L
)
C:\test scripts>(
SET _mth=01
 SET _day=25
 SET _yr=2010
)
C:\test scripts>SET /A _month=((01-14)/12)
C:\test scripts>SET /A _year=(2010+4800)
C:\test scripts>SET /A _jdate=((1461*(6810+-1)/4)+((367*((01-2)-(12*-1)))/12))-((3*((6810+-1+100)/100))/4)
+(25-32075)
C:\test scripts>SET _mth=
C:\test scripts>SET _day=
C:\test scripts>SET _yr=
C:\test scripts>SET _month=
C:\test scripts>SET _year=
C:\test scripts>IF NOT 0 == 1 GOTO :EOF
```
If you take a look at the errors, I have the following errors happening but it only happens on certain ones.

C:\test scripts>SET /A _month=((08-14)/12)
Invalid number. Numeric constants are either decimal (17),
hexadecimal (0x11), or octal (021).

C:\test scripts>SET /A _jdate=((1461*(6809+)/4)+((367*((08-2)-(12*)))/12))-((3*((6809++100)/100))/4)+(24-3
2075)
Missing operand.

Other times the same thing works perfectly such as the following in the same script. Any reasons why?

C:\test scripts>SET /A _jdate=((1461*(6809+0)/4)+((367*((12-2)-(12*0)))/12))-((3*((6809+0+100)/100))/4)+(2
3-32075)
C:\test scripts>SET _mth=


----------



## scrfix (May 3, 2009)

Okay,

I did some research on this subject. Those errors are caused by the original programmer of the command line structure programming the SET function that if they see a leading 0 it is believed to be octal. Since 08 is an invalid octal number this error comes up. Now, the repair for this is supposed to be the following.

set /A dd=1%dd% - 100

I haven't tested this yet however it looks like it would work.
It takes and adds a 1 before the number and then subtracts 100 therefore never becoming an octal number.


----------



## scrfix (May 3, 2009)

I now have an issue that I once again think has to do with the DelayedExpansion but I could be wrong. It wouldn't be the first time. 

*Code*

```
echo off
:: initalize variables
 
SET _dt=DATE /t
SET /A _count=1
CALL :_JDateConversion
GOTO _GetDirDates
 
:_JDateConversion
FOR /F "tokens=1-4 delims=/ " %%I IN ('%_dt%') DO (
SET _mth=%%J
SET _day=%%K
SET /A _yr=%%L
SET /A _mth=1%_mth% - 100
SET /A _day=1%_day% - 100
)
 
SET /A _month=((%_mth%-14)/12)
SET /A _year=(%_yr%+4800)
SET /A _jdate=((1461*(%_year%+%_month%)/4)+((367*((%_mth%-2)-(12*%_month%)))/12))-((3*((%_year%+%_month%+100)/100))/4)+(%_day%-32075)
 
SET _mth=
SET _day=
SET _yr=
SET _month=
SET _year=
IF NOT %_count%==1 GOTO :EOF
IF %_count%==1 (
CALL :_StoreCurrentJulianDate
)
 
set /A _count=0
GOTO _GetDirDates
 
:_StoreCurrentJulianDate
SET _currentjdate=%_jdate%
SET _jdate=
GOTO :EOF
 
:_GetDirDates
SETLocal EnableDelayedExpansion
For /F "Tokens=1,4* skip=7" %%I In ('Dir /AD-L /OD /TC^|Findstr /L /V "File(s) Dir(s)"') Do (
SET _dcd=%%I
SET _dt=Echo.skip %%I
SET _dirname=%%K
CALL :_JDateConversion
Echo Current Date=!_dt!
Echo Current JDate=!_currentjdate!
Echo Directory=!_dirname!
Echo Directory Creation Date=!_dcd!
Echo Directory Creation JDate=!_jdate!
SET /A _math=!_currentjdate!-!_jdate!
Echo !_dirname! is !_math! jdays old
Echo.
)
 
:: FOR /F "tokens=1 skip=7" %%I IN ('dir /AD-L /OD /T:C') DO Echo %%I
:: For /F "Tokens=1,2,4* skip=4" %%I In ('Dir /AD-L /OD /TC') Do If Not %%L==. If Not %%L==.. If Not "%%J"=="File(s)" If Not "%%J"=="Dir(s)" SET _dirdate=%%I SET _dirname=%%L SET _dirdate=%_dirdate:/=% echo %_dirname%
SETLocal DisableDelayedExpansion
GOTO :EOF
```
*Output*

```
Current Date=Echo.skip 05/02/2009
Current JDate=2452054
Directory=file test
Directory Creation Date=05/02/2009
Directory Creation JDate=2451689
file test is 365 jdays old
 
Current Date=Echo.skip 05/14/2009
Current JDate=2452054
Directory=Test Files
Directory Creation Date=05/14/2009
Directory Creation JDate=2451689
Test Files is 365 jdays old
 
Current Date=Echo.skip 05/17/2009
Current JDate=2452054
Directory=Icon Files
Directory Creation Date=05/17/2009
Directory Creation JDate=2451689
Icon Files is 365 jdays old
 
Current Date=Echo.skip 06/25/2009
Current JDate=2452054
Directory=testing
Directory Creation Date=06/25/2009
Directory Creation JDate=2451689
testing is 365 jdays old
 
Current Date=Echo.skip 08/24/2009
Current JDate=2452054
Directory=Mirror Yes
Directory Creation Date=08/24/2009
Directory Creation JDate=2451689
Mirror Yes is 365 jdays old
 
Current Date=Echo.skip 09/26/2009
Current JDate=2452054
Directory=Chantilly Homes
Directory Creation Date=09/26/2009
Directory Creation JDate=2451689
Chantilly Homes is 365 jdays old
 
Current Date=Echo.skip 12/23/2009
Current JDate=2452054
Directory=Walker
Directory Creation Date=12/23/2009
Directory Creation JDate=2451689
Walker is 365 jdays old
 
Current Date=Echo.skip 01/07/2010
Current JDate=2452054
Directory=runonly
Directory Creation Date=01/07/2010
Directory Creation JDate=2452054
runonly is 0 jdays old
 
Current Date=Echo.skip 01/08/2010
Current JDate=2452054
Directory=01-06-10
Directory Creation Date=01/08/2010
Directory Creation JDate=2452054
01-06-10 is 0 jdays old
 
Current Date=Echo.skip 01/08/2010
Current JDate=2452054
Directory=Old Stuff
Directory Creation Date=01/08/2010
Directory Creation JDate=2452054
Old Stuff is 0 jdays old
 
Current Date=Echo.skip 05/02/2009
Current JDate=2452054
Directory=file test
Directory Creation Date=05/02/2009
Directory Creation JDate=2451689
file test is 365 jdays old
 
Current Date=Echo.skip 05/14/2009
Current JDate=2452054
Directory=Test Files
Directory Creation Date=05/14/2009
Directory Creation JDate=2451689
Test Files is 365 jdays old
 
Current Date=Echo.skip 05/17/2009
Current JDate=2452054
Directory=Icon Files
Directory Creation Date=05/17/2009
Directory Creation JDate=2451689
Icon Files is 365 jdays old
 
Current Date=Echo.skip 06/25/2009
Current JDate=2452054
Directory=testing
Directory Creation Date=06/25/2009
Directory Creation JDate=2451689
testing is 365 jdays old
 
Current Date=Echo.skip 08/24/2009
Current JDate=2452054
Directory=Mirror Yes
Directory Creation Date=08/24/2009
Directory Creation JDate=2451689
Mirror Yes is 365 jdays old
 
Current Date=Echo.skip 09/26/2009
Current JDate=2452054
Directory=Chantilly Homes
Directory Creation Date=09/26/2009
Directory Creation JDate=2451689
Chantilly Homes is 365 jdays old
 
Current Date=Echo.skip 12/23/2009
Current JDate=2452054
Directory=Walker
Directory Creation Date=12/23/2009
Directory Creation JDate=2451689
Walker is 365 jdays old
 
Current Date=Echo.skip 01/07/2010
Current JDate=2452054
Directory=runonly
Directory Creation Date=01/07/2010
Directory Creation JDate=2452054
runonly is 0 jdays old
 
Current Date=Echo.skip 01/08/2010
Current JDate=2452054
Directory=01-06-10
Directory Creation Date=01/08/2010
Directory Creation JDate=2452054
01-06-10 is 0 jdays old
 
Current Date=Echo.skip 01/08/2010
Current JDate=2452054
Directory=Old Stuff
Directory Creation Date=01/08/2010
Directory Creation JDate=2452054
Old Stuff is 0 jdays old
```
The issues that I am having are as follows:

1. It repeats the same folders over and over again? Why? Is there something in there telling it to do that? Not that I can see but there must be because it is doing that.

2. It doesn't figure some of the dates correctly when finding out the julian dates for the creation date of the directories.

Can you help point me in the correct direction for this?


----------



## TheOutcaste (Aug 8, 2007)

You are running the _GetDirDates code twice:
Here's the sequence (pseudocode, not actual)

```
set _count=1
call _jdateconversion
     call storecurrentjdate and return
     set _count=0
     goto _GetDirDates [COLOR=Red]<====This should be Goto:EOF[/COLOR]
   ::  start loop to get info
     for each Directory
         call _jdateconversion and return
     Echo info
Return (from the first call to _jdateconversion)
goto _GetDirDates
 ::start loop to get info
     for each Directory
         call _jdateconversion and return
     Echo info
return
```
Your conversion routine is inside a loop, but is using %var% instead of !var!, so is calculating the Julian date incorrectly. Day and Month are always set to 99 (1-100)
So you are calculating the Julian date for 99/99/2010 for today, and 99/99/2009 for the creation dates, which are exactly 365 days apart
99/99/2010=2452054
99/99/2009=2451689
Today (Jan 25th) is Julian 2455222

```
:_JDateConversion
FOR /F "tokens=1-4 delims=/ " %%I IN ('%_dt%') DO (
SET _mth=%%J
SET _day=%%K
SET /A _yr=%%L
SET /A _mth=1[COLOR=Red][B]%[/B][/COLOR]_mth[COLOR=Red][B]%[/B][/COLOR] - 100
SET /A _day=1[COLOR=Red][B]%[/B][/COLOR]_day[COLOR=Red][B]%[/B][/COLOR] - 100
)
```
EDIT: You'll need to enable delayed expansion before calling this loop for the current date.

You can also use this to remove leading zeros from 2 digit numbers. I don't know which is faster.

If 1!_mth! LSS 110 Set _mth=!_mth:~-1!


----------



## scrfix (May 3, 2009)

That seems to work. Now it is just a matter of writing the If statement. Thanks for the help in this.


----------



## scrfix (May 3, 2009)

*Final Product*


```
echo off
:: NOTES
:: Very important!  If you choose to comment out the RD command and enable the DEL command, this
:: program currently checks the creation date on directories and based upon that it will delete
:: the files.  This program looks only in the current directory you run the program from.
 
:: Here you can
:: 1. Set Test Mode On or Off (On by default)
:: 2. Adjust the number of julian days need to pass before directory or file removal.
:: 3. Set the program to Remove the entire directory or just the files within the directory
 
SET _TestMode=ON
SET /A _daycount=30
SET _RmvCom=RD /S /Q
:: SET _RmvCom=DEL /F /S /Q
 
:: initalize other variables that shouldn't be changed
SET _dt=DATE /t
SET /A _count=1
IF /i NOT %_TestMode%==ON Set _Test=
IF /i %_TestMode%==ON SET _Test=Echo 
 
SETLocal EnableDelayedExpansion
CALL :_JDateConversion
GOTO _GetDirDates
 
:_JDateConversion
FOR /F "tokens=1-4 delims=/ " %%I IN ('%_dt%') DO (
SET _mth=%%J
SET _day=%%K
SET /A _yr=%%L
SET /A _mth=1!_mth! - 100
SET /A _day=1!_day! - 100
)

SET /A _month=((%_mth%-14)/12)
SET /A _year=(%_yr%+4800)
SET /A _jdate=((1461*(%_year%+%_month%)/4)+((367*((%_mth%-2)-(12*%_month%)))/12))-((3*((%_year%+%_month%+100)/100))/4)+(%_day%-32075)
SET _mth=
SET _day=
SET _yr=
SET _month=
SET _year=
IF NOT %_count%==1 CALL :_DirRemoval&GOTO :EOF
IF %_count%==1 (
CALL :_StoreCurrentJulianDate
)
set /A _count=0
GOTO :EOF
 
:_StoreCurrentJulianDate
SET _currentjdate=%_jdate%
SET _jdate=
GOTO :EOF
 
:_DirRemoval
SET /A _math=!_currentjdate!-!_jdate!
IF !_math! GEQ !_daycount! (
%_Test%!_RmvCom! "!_dirname!"
)
GOTO :EOF
 
:_GetDirDates
For /F "Tokens=1,4* skip=7" %%I In ('Dir /AD-L /OD /TC^|Findstr /L /V "File(s) Dir(s)"') Do (
SET _dt=Echo.skip %%I
SET _dirname=%%K
CALL :_JDateConversion
)

SETLocal DisableDelayedExpansion
GOTO :EOF
```
This will be extremely helpful for the directories that need to be removed after a certain period of time. I wish they would just include an option that says hey the directory is so many days old, delete it within the RD function.


----------



## dcohn (Jan 29, 2010)

Forfiles is the best solution

It can delete directories using this format

forfiles -pc:/BACKUP -mTemp -s -c"CMD /C if @ISDIR==TRUE RD/s" 

You would need to use the date portion if the command of course.


----------



## Squashman (Apr 4, 2003)

dcohn said:


> Forfiles is the best solution
> 
> It can delete directories using this format
> 
> ...


I had suggested that earlier in the thread but the user wants to delete based on Created Date, not modified date.


----------



## dcohn (Jan 29, 2010)

Understood. Sorry I missed that.

Personally I would be a little uncomfortable with this script.

Seems too complex for the task for my taste. I would try to find a more suitable tool for the solution.

In this case I would use JPSoft Take command instead of the built in command processor. The free TCC LE version has the date commands built in along with options for using create instead of modified dates. I am not 100% sure the free version does all you need but I believe it may.

http://jpsoft.com/help/dateranges.htm
http://jpsoft.com/help/del.htm?zoom_highlightsub=delete+by+date

Here is an example line that would delete files and empty subfolders that 10 days or older by create date. It would exclude folder.cfg and include hidden and read only.

del /[dc-10,1/1/80] /[!folder.cfg] /s /x /y i:\*.*

You can do anything in TakeCommand TCC. There is no scripting product better suited for this type of work within windows. Noty even PowerShell has the power of TakeCommand. It allows you to create your own functions, aliases and plugins. Very well supported product as well.

http://jpsoft.com/ If anyone knows of another product with the same power, flexibility, STABILITY and support please let me know.

I recently found this tool that may work for just the deleting aged files but unsure because I have not tested. TCC can be a lot of work initially and unless you require the command processor often it may be overkill.

http://home.mnet-online.de/horst.muc/win/delage.htm

Quite nice really if it suits your need. Deletes by date but no folders unless empty. Perfect for a task I have that must parse through a folder structure with 3 million files and delete those over 95 days. Just unsure I can use it in 64 bit windows. Going to test.

Also if you have access to Experts Exchange there is a very simple vbscript and a Cmd batch file similar to what you wrote but more compact. It may not do what you need precisely though it does have the create date code.

http://www.experts-exchange.com/OS/Microsoft_Operating_Systems/MS_DOS/Q_24129205.html


----------



## Squashman (Apr 4, 2003)

Swiss File Knife is one of my favorite cmd line tools. I think it could probably accomplish this task as well but I am not sure.
http://stahlworks.com/dev/swiss-file-knife.html


----------

