Delete files older than 3 months old in a directory using .NET

158,321

Solution 1

Something like this outta do it.

using System.IO; 

string[] files = Directory.GetFiles(dirName);

foreach (string file in files)
{
   FileInfo fi = new FileInfo(file);
   if (fi.LastAccessTime < DateTime.Now.AddMonths(-3))
      fi.Delete();
}

Solution 2

Here's a 1-liner lambda:

Directory.GetFiles(dirName)
         .Select(f => new FileInfo(f))
         .Where(f => f.LastAccessTime < DateTime.Now.AddMonths(-3))
         .ToList()
         .ForEach(f => f.Delete());

Solution 3

For those that like to over-use LINQ.

(from f in new DirectoryInfo("C:/Temp").GetFiles()
 where f.CreationTime < DateTime.Now.Subtract(TimeSpan.FromDays(90))
 select f
).ToList()
    .ForEach(f => f.Delete());

Solution 4

Here's a snippet of how to get the creation time of files in the directory and find those which have been created 3 months ago (90 days ago to be exact):

    DirectoryInfo source = new DirectoryInfo(sourceDirectoryPath);

    // Get info of each file into the directory
    foreach (FileInfo fi in source.GetFiles())
    {
        var creationTime = fi.CreationTime;

        if(creationTime < (DateTime.Now- new TimeSpan(90, 0, 0, 0)))
        {
            fi.Delete();
        }
    }

Solution 5

The most canonical approach when wanting to delete files over a certain duration is by using the file's LastWriteTime (Last time the file was modified):

Directory.GetFiles(dirName)
         .Select(f => new FileInfo(f))
         .Where(f => f.LastWriteTime < DateTime.Now.AddMonths(-3))
         .ToList()
         .ForEach(f => f.Delete());

(The above based on Uri's answer but with LastWriteTime.)

Whenever you hear people talking about deleting files older than a certain time frame (which is a pretty common activity), doing it based on the file's LastModifiedTime is almost always what they are looking for.

Alternatively, for very unusual circumstances you could use the below, but use these with caution as they come with caveats.

CreationTime
.Where(f => f.CreationTime < DateTime.Now.AddMonths(-3))

The time the file was created in the current location. However, be careful if the file was copied, it will be the time it was copied and CreationTime will be newer than the file's LastWriteTime.

LastAccessTime
.Where(f => f.LastAccessTime < DateTime.Now.AddMonths(-3))

If you want to delete the files based on the last time they were read you could use this but, there is no guarantee it will be updated as it can be disabled in NTFS. Check fsutil behavior query DisableLastAccess to see if it is on. Also under NTFS it may take up to an hour for the file's LastAccessTime to update after it was accessed.

Share:
158,321
JL.
Author by

JL.

Developer, Designer , Coder

Updated on September 12, 2021

Comments

  • JL.
    JL. over 2 years

    I would like to know (using C#) how I can delete files in a certain directory older than 3 months, but I guess the date period could be flexible.

    Just to be clear: I am looking for files that are older than 90 days, in other words files created less than 90 days ago should be kept, all others deleted.

  • JL.
    JL. over 14 years
    Thanks, I noticed you're using lastAccessTime, is this the creation time?
  • Admin
    Admin over 14 years
    no, as propertyNames says: LastAccessTime - you should go for property CreationTime if you'd like to!
  • Steve Danner
    Steve Danner over 14 years
    Yeah, which property you use is entirely up to you. You could also use LastWriteTime if you wanted.
  • JL.
    JL. over 14 years
    Sorry to ask, but are you 100% sure about the comparison operator being less than? does this mean that the first date should be less than the 2nd date?
  • Steve Danner
    Steve Danner over 14 years
    No need to apologize, that is how you learn! Yes, I'm positive. It means the last access time on the file is less than the date 3 months ago from this moment.
  • JL.
    JL. over 14 years
    Ok thanks Steve, you got here first with a great answer, thanks again!
  • Ta01
    Ta01 over 14 years
    var filesToDelete = new DirectoryInfo(@"C:\Temp").GetFiles().Where(x=>x.LastAccessTi‌​me < DateTime.Now.AddMonths(-3)); //variation
  • Filip Ekberg
    Filip Ekberg over 14 years
    Woho! Someone else than me thinks over-using LINQ is awesome! ;)
  • Joel Mueller
    Joel Mueller over 14 years
    What does the .ToList() call add other than a second loop through the matched files?
  • JamesUsedHarden
    JamesUsedHarden over 14 years
    @Joel Mueller. List<T> defines a ForEach method which can be used to apply an Action<T> to all elements. Unfortunately there is no such extension method for IEnumerable<T>.
  • Joel Mueller
    Joel Mueller over 14 years
    Good point. I wrote my own ForEach extension method for IEnumerable<T> so long ago, I sometimes forget it isn't built in.
  • Dynami Le Savard
    Dynami Le Savard over 14 years
    No need for ToList(), DirectoryInfo.GetFiles() returns a FileInfo[].
  • Mario The Spoon
    Mario The Spoon about 13 years
    +1 for helping me out. Instead of creating a new FileInfo instance you could use File.GetCreationTime or File.GetLastAccessTime. Should be a minor performance improvement.
  • abrkn
    abrkn over 11 years
    For those with no shame: new DirectoryInfo(@"C:\Temp").GetFiles("*.log").AsParallel().Whe‌​re(f => f.LastWriteTime < DateTime.Now - TimeSpan.FromDays(90)).ForAll(f => f.Delete());
  • JamesUsedHarden
    JamesUsedHarden over 11 years
    Since the tasks are all reading/writing from the same disk I'm not sure AsParallel is really appropriate here. It'd be good to test to be sure.
  • Andrew Hagner
    Andrew Hagner almost 11 years
    I guess GetFiles and Delete never fail in your environment? Just pointing that out since this seems to be a highly referenced answer.
  • Andrew Hagner
    Andrew Hagner almost 11 years
    How would you handle a failed call to Delete via this Linq version?
  • JamesUsedHarden
    JamesUsedHarden over 10 years
    @AndrewHagner, I would add a new utility method like DeleteSafe() and include error handling in that to never throw an error even if delete fails.
  • Daniel
    Daniel over 7 years
    90 days <> 3 months
  • James Love
    James Love over 7 years
    @VladL I get a "IEnumerable<FileInfo> does not contain ForEach" if I drop the ToList(). I just kept it in.
  • Chad
    Chad about 7 years
    You should declare a new variable outside the foreach() loop to hold the value of (DateTime.Now- new TimeSpan(90, 0, 0, 0)). There is no reason to calculate that repeatedly in the loop.
  • H20rider
    H20rider about 7 years
    I like this. But I would wrap the delete in a try/catch
  • Allan F
    Allan F about 5 years
    LastWriteTime is the datetime visible in standard file explorer .. I'm going with a test against this attribute. Yep - I would put in a try catch ..
  • Vojtěch Dohnal
    Vojtěch Dohnal almost 5 years
    new DirectoryInfo(dir).GetFiles() is faster than new FileInfo(f) for every single file.
  • Armando Contestabile
    Armando Contestabile about 2 years
    Why do evaluate each loop DateTime.Now.AddMonths(-3) ?