使用 .NET 删除目录中超过 3 个月的文件

Posted

技术标签:

【中文标题】使用 .NET 删除目录中超过 3 个月的文件【英文标题】:Delete files older than 3 months old in a directory using .NET 【发布时间】:2011-01-14 09:46:23 【问题描述】:

我想知道(使用 C#)我如何删除某个目录中超过 3 个月的文件,但我想日期时间段可能是灵活的。

请明确一点:我正在寻找超过 90 天的文件,换句话说,应该保留 90 天前创建的文件,删除所有其他文件。

【问题讨论】:

如果文件量很大,最好使用 EnumerateFiles 和 EnumerateDirectories 而不是 GetFiles 和 GetDirectories,因为它们直接运行枚举而不是收集列表。但是,您必须使用 foreach 循环。 【参考方案1】:

System.IO.File 类上的GetLastAccessTime 属性应该会有所帮助。

【讨论】:

【参考方案2】:

基本上,您可以使用 Directory.Getfiles(Path) 来获取所有文件的列表。之后,您遍历列表并按照 Keith 的建议调用 GetLastAccessTim()。

【讨论】:

【参考方案3】:

你只需要FileInfo -> CreationTime

而不仅仅是计算时间差。

在 app.config 中,您可以保存 TimeSpan 值,该值表示文件必须被删除多长时间

还可以查看DateTime Subtract 方法。

祝你好运

【讨论】:

【参考方案4】:

这里有一个sn-p,如何获取目录中文件的创建时间并找到3个月前(准确地说是90天前)创建的文件:

    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();
        
    

【讨论】:

不需要ToList()DirectoryInfo.GetFiles() 返回一个FileInfo[] 您应该在foreach() 循环之外声明一个新变量来保存(DateTime.Now- new TimeSpan(90, 0, 0, 0)) 的值。没有理由在循环中重复计算。【参考方案5】:

或者,如果您需要根据创建日期删除文件,您可以使用File.GetCreationTime Method。

【讨论】:

【参考方案6】:

这样的事情不能做。

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();

【讨论】:

谢谢,我注意到您使用的是 lastAccessTime,这是创建时间吗? 不,正如 propertyNames 所说:LastAccessTime - 如果你愿意,你应该去CreationTime 的财产! 是的,您使用哪个属性完全取决于您。如果需要,您也可以使用 LastWriteTime。 +1 帮助我。您可以使用 File.GetCreationTime 或 File.GetLastAccessTime,而不是创建新的 FileInfo 实例。应该是一个小的性能改进。 我猜 GetFiles 和 Delete 在您的环境中永远不会失败?只是指出这一点,因为这似乎是一个高度引用的答案。【参考方案7】:

对于那些喜欢过度使用 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());

【讨论】:

var filesToDelete = new DirectoryInfo(@"C:\Temp").GetFiles().Where(x=>x.LastAccessTime 哇!除了我之外,其他人认为过度使用 LINQ 很棒! ;) .ToList() 调用除了通过匹配的文件进行第二次循环之外还添加了什么? @Joel Mueller。 List&lt;T&gt; 定义了一个ForEach 方法,可用于将Action&lt;T&gt; 应用于所有元素。不幸的是,IEnumerable&lt;T&gt; 没有这样的扩展方法。 好点。很久以前我为IEnumerable&lt;T&gt;写了自己的ForEach扩展方法,我有时会忘记它不是内置的。【参考方案8】:

这是一个 1-liner lambda:

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

【讨论】:

@VladL 如果我删除 ToList(),我会得到一个“IEnumerable 不包含 ForEach”。我只是把它放在里面。 我喜欢这个。但我会将删除包装在 try/catch 中 new DirectoryInfo(dir).GetFiles() 对于每个文件都比 new FileInfo(f) 快。【参考方案9】:

类似的东西

            foreach (FileInfo file in new DirectoryInfo("SomeFolder").GetFiles().Where(p => p.CreationTime < DateTime.Now.AddDays(-90)).ToArray())
                File.Delete(file.FullName);

【讨论】:

【参考方案10】:
            system.IO;

             List<string> DeletePath = new List<string>();
            DirectoryInfo info = new DirectoryInfo(Server.MapPath("~\\TempVideos"));
            FileInfo[] files = info.GetFiles().OrderBy(p => p.CreationTime).ToArray();
            foreach (FileInfo file in files)
            
                DateTime CreationTime = file.CreationTime;
                double days = (DateTime.Now - CreationTime).TotalDays;
                if (days > 7)
                
                    string delFullPath = file.DirectoryName + "\\" + file.Name;
                    DeletePath.Add(delFullPath);
                
            
            foreach (var f in DeletePath)
            
                if (File.Exists(F))
                
                    File.Delete(F);
                
            

用于页面加载或网络服务或任何其他用途。

我的概念是 evrry 7 天我必须在不使用 DB 的情况下删除文件夹文件

【讨论】:

【参考方案11】:
         //Store the number of days after which you want to delete the logs.
         int Days = 30;

          // Storing the path of the directory where the logs are stored.
           String DirPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).Substring(6) + "\\Log(s)\\";

          //Fetching all the folders.
            String[] objSubDirectory = Directory.GetDirectories(DirPath);

            //For each folder fetching all the files and matching with date given 
            foreach (String subdir in objSubDirectory)     
            
                //Getting the path of the folder                 
                String strpath = Path.GetFullPath(subdir);
                //Fetching all the files from the folder.
                String[] strFiles = Directory.GetFiles(strpath);
                foreach (string files in strFiles)
                
                    //For each file checking the creation date with the current date.
                    FileInfo objFile = new FileInfo(files);
                    if (objFile.CreationTime <= DateTime.Now.AddDays(-Days))
                    
                        //Delete the file.
                        objFile.Delete();
                    
                

                //If folder contains no file then delete the folder also.
                if (Directory.GetFiles(strpath).Length == 0)
                
                    DirectoryInfo objSubDir = new DirectoryInfo(subdir);
                    //Delete the folder.
                    objSubDir.Delete();
                

            

【讨论】:

【参考方案12】:

我试过这段代码,效果很好,希望得到回答

namespace EraseJunkFiles

    class Program
    
        static void Main(string[] args)
        
            DirectoryInfo yourRootDir = new DirectoryInfo(@"C:\yourdirectory\");
            foreach (FileInfo file in yourRootDir.GetFiles())
                if (file.LastWriteTime < DateTime.Now.AddDays(-90))
                    file.Delete();
        
    

【讨论】:

90 天 3 个月【参考方案13】:

只需创建一个可以帮助您完成此任务的小删除功能,我已经测试了这段代码,它运行得很好。

此功能会删除 90 天 之前的文件以及要从文件夹中删除的扩展名为 .zip 的文件。

Private Sub DeleteZip()

    Dim eachFileInMydirectory As New DirectoryInfo("D:\Test\")
    Dim fileName As IO.FileInfo

    Try
        For Each fileName In eachFileInMydirectory.GetFiles
            If fileName.Extension.Equals("*.zip") AndAlso (Now - fileName.CreationTime).Days > 90 Then
                fileName.Delete()
            End If
        Next

    Catch ex As Exception
        WriteToLogFile("No Files older than 90 days exists be deleted " & ex.Message)
    End Try
End Sub

【讨论】:

【参考方案14】:

例如: 要在源代码上运行我的文件夹项目,我需要创建两个文件夹。 我将这个算法设置为每周 2 天并分成 4 小时

public static void LimpiarArchivosViejos()
    
        DayOfWeek today = DateTime.Today.DayOfWeek;
        int hora = DateTime.Now.Hour;
        if(today == DayOfWeek.Monday || today == DayOfWeek.Tuesday && hora < 12 && hora > 8)
        
            CleanPdfOlds();
            CleanExcelsOlds();
        

    
    private static void CleanPdfOlds()
        string[] files = Directory.GetFiles("../../Users/Maxi/Source/Repos/13-12-2017_config_pdfListados/ApplicaAccWeb/Uploads/Reports");
        foreach (string file in files)
        
            FileInfo fi = new FileInfo(file);
            if (fi.CreationTime < DateTime.Now.AddDays(-7))
                fi.Delete();
        
    
    private static void CleanExcelsOlds()
    
        string[] files2 = Directory.GetFiles("../../Users/Maxi/Source/Repos/13-12-2017_config_pdfListados/ApplicaAccWeb/Uploads/Excels");
        foreach (string file in files2)
        
            FileInfo fi = new FileInfo(file);
            if (fi.CreationTime < DateTime.Now.AddDays(-7))
                fi.Delete();
        
    

【讨论】:

【参考方案15】:

我在作为服务运行的控制台应用程序中使用以下内容从 App.Settings 文件中获取目录信息。保留文件的天数也是可配置的,乘以 -1 可在 DateTime.Now 的 AddDays() 方法中使用。

static void CleanBackupFiles()
        
            string gstrUncFolder = ConfigurationManager.AppSettings["DropFolderUNC"] + "";
            int iDelAge = Convert.ToInt32(ConfigurationManager.AppSettings["NumDaysToKeepFiles"]) * -1;
            string backupdir = string.Concat(@"\", "Backup", @"\");

            string[] files = Directory.GetFiles(string.Concat(gstrUncFolder, backupdir));


            foreach (string file in files)
            
                FileInfo fi = new FileInfo(file);
                if (fi.CreationTime < DateTime.Now.AddDays(iDelAge))
                
                    fi.Delete();
                
            

        

【讨论】:

【参考方案16】:

SSIS 类型的示例 ..(如果这对任何人都有帮助)

          public void Main()
          
                 // TODO: Add your code here
        // Author: Allan F 10th May 2019

        //first part of process .. put any files of last Qtr (or older) in Archive area 
        //e.g. if today is 10May2019 then last quarter is 1Jan2019 to 31March2019 .. any files earlier than 31March2019 will be archived

        //string SourceFileFolder = "\\\\adlsaasf11\\users$\\aford05\\Downloads\\stage\\";
        string SourceFilesFolder = (string)Dts.Variables["SourceFilesFolder"].Value;
        string ArchiveFolder = (string)Dts.Variables["ArchiveFolder"].Value;
        string FilePattern = (string)Dts.Variables["FilePattern"].Value;
        string[] files = Directory.GetFiles(SourceFilesFolder, FilePattern);

        //DateTime date = new DateTime(2019, 2, 15);//commented out line .. just for testing the dates .. 

        DateTime date = DateTime.Now;
        int quarterNumber = (date.Month - 1) / 3 + 1;
        DateTime firstDayOfQuarter = new DateTime(date.Year, (quarterNumber - 1) * 3 + 1, 1);
        DateTime lastDayOfQuarter = firstDayOfQuarter.AddMonths(3).AddDays(-1);

        DateTime LastDayOfPriorQuarter = firstDayOfQuarter.AddDays(-1);
        int PrevQuarterNumber = (LastDayOfPriorQuarter.Month - 1) / 3 + 1;
        DateTime firstDayOfLastQuarter = new DateTime(LastDayOfPriorQuarter.Year, (PrevQuarterNumber - 1) * 3 + 1, 1);
        DateTime lastDayOfLastQuarter = firstDayOfLastQuarter.AddMonths(3).AddDays(-1);

        //MessageBox.Show("debug pt2: firstDayOfQuarter" + firstDayOfQuarter.ToString("dd/MM/yyyy"));
        //MessageBox.Show("debug pt2: firstDayOfLastQuarter" + firstDayOfLastQuarter.ToString("dd/MM/yyyy"));


        foreach (string file in files)
        
            FileInfo fi = new FileInfo(file);

            //MessageBox.Show("debug pt2:" + fi.Name + " " + fi.CreationTime.ToString("dd/MM/yyyy HH:mm") + " " + fi.LastAccessTime.ToString("dd/MM/yyyy HH:mm") + " " + fi.LastWriteTime.ToString("dd/MM/yyyy HH:mm"));
            if (fi.LastWriteTime < firstDayOfQuarter)
            

                try
                

                    FileInfo fi2 = new FileInfo(ArchiveFolder);

                    //Ensure that the target does not exist.
                    //fi2.Delete();

                    //Copy the file.
                    fi.CopyTo(ArchiveFolder + fi.Name);
                    //Console.WriteLine("0 was copied to 1.", path, ArchiveFolder);

                    //Delete the old location file.
                    fi.Delete();
                    //Console.WriteLine("0 was successfully deleted.", ArchiveFolder);

                
                catch (Exception e)
                
                    //do nothing
                    //Console.WriteLine("The process failed: 0", e.ToString());
                
            
        

        //second part of process .. delete any files in Archive area dated earlier than last qtr ..
        //e.g. if today is 10May2019 then last quarter is 1Jan2019 to 31March2019 .. any files earlier than 1Jan2019 will be deleted

        string[] archivefiles = Directory.GetFiles(ArchiveFolder, FilePattern);
        foreach (string archivefile in archivefiles)
        
            FileInfo fi = new FileInfo(archivefile);
            if (fi.LastWriteTime < firstDayOfLastQuarter )
            
                try
                
                    fi.Delete();
                
                catch (Exception e)
                
                    //do nothing
                
            
        


                 Dts.TaskResult = (int)ScriptResults.Success;
          

【讨论】:

【参考方案17】:

由于new FileInfo(filePath) 的解决方案不易测试,我建议像DirectoryFilePath 这样的类使用包装器:

public interface IDirectory

    string[] GetFiles(string path);


public sealed class DirectoryWrapper : IDirectory

    public string[] GetFiles(string path) => Directory.GetFiles(path);


public interface IFile

    void Delete(string path);
    DateTime GetLastAccessTime(string path);


public sealed class FileWrapper : IFile

    public void Delete(string path) => File.Delete(path);
    public DateTime GetLastAccessTimeUtc(string path) => File.GetLastAccessTimeUtc(path);


然后使用这样的东西:

public sealed class FooBar

    public FooBar(IFile file, IDirectory directory)
    
        File = file;
        Directory = directory;
    

    private IFile File  get; 
    private IDirectory Directory  get; 

    public void DeleteFilesBeforeTimestamp(string path, DateTime timestamp)
    
        if(!Directory.Exists(path))
            throw new DirectoryNotFoundException($"The path path was not found.");

        var files = Directory
            .GetFiles(path)
            .Select(p => new
            
                Path = p,
                // or File.GetLastWriteTime() or File.GetCreationTime() as needed
                LastAccessTimeUtc = File.GetLastAccessTimeUtc(p) 
            )
            .Where(p => p.LastAccessTimeUtc < timestamp);

        foreach(var file in files)
        
            File.Delete(file.Path);
        
    

【讨论】:

【参考方案18】:

当想要在一定时间内删除文件时,最规范的方法是使用文件的 LastWriteTime(上次修改文件的时间):

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

(以上基于 Uri 的回答,但使用LastWriteTime。)

每当您听到人们谈论删除超过某个时间范围的文件(这是一种非常常见的活动)时,根据文件的 LastModifiedTime 执行此操作几乎总是他们想要的。

或者,对于非常不寻常的情况,您可以使用以下内容,但请谨慎使用,因为它们带有警告。

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

文件在当前位置创建的时间。但是,如果文件已被复制,请注意,这将是它被复制的时间,CreationTime 将比文件的LastWriteTime更新

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

如果您想根据上次读取文件的时间删除文件,您可以使用它,但不能保证它会被更新,因为它可以在 NTFS 中禁用。检查fsutil behavior query DisableLastAccess 以查看它是否已打开。同样在 NTFS 下,文件的 LastAccessTime 在被访问后可能需要长达一个小时才能更新。

【讨论】:

以上是关于使用 .NET 删除目录中超过 3 个月的文件的主要内容,如果未能解决你的问题,请参考以下文章

Codeigniter 3:删除所有超过 2 个月的行

CMD 删除特定文件夹中超过 X 天的文件

如何使用 gsutil 从文件名中删除 .jpg 已在存储桶中超过 20000 个文件

Android中超过30000张图片的快速删除文件夹

需要在删除和插入模式下将最近 5 个月的数据存储在表中

Chrome使用技巧(几个月的心得)