使用.NET删除目录中3个月以上的文件


117

我想知道(使用C#)如何删除3个月以上的某个目录中的文件,但是我认为日期期限可能会很灵活。

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


如果有大量文件,则最好使用EnumerateFiles和EnumerateDirectories而不是GetFiles和GetDirectories,因为它们直接运行枚举而不是收集列表。但是,您将必须使用foreach循环。
拉里

Answers:


257

像这样的事情不能做到。

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,这是创建时间吗?
JL。

10
不,正如propertyNames所说:LastAccessTime- CreationTime如果愿意,您应该去寻求财产!
Andreas Niedermair'2

4
是的,您使用哪种财产完全取决于您。如果需要,也可以使用LastWriteTime。
史蒂夫·丹纳

3
+1帮助我。可以使用File.GetCreationTime或File.GetLastAccessTime代替创建新的FileInfo实例。应该对性能进行较小的改进。
Mario The Spoon

5
我猜GetFiles和Delete在您的环境中永远不会失败?只是指出这一点,因为这似乎是一个被高度引用的答案。
Andrew Hagner 2013年

93

这是1层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 <FileInfo>不包含ForEach”的信息。我只是不停地进去。
詹姆斯爱情

3
我喜欢这个。但我会将删除内容包装在try / catch中
H20rider

new DirectoryInfo(dir).GetFiles()new FileInfo(f)每个文件都快。
Vojtěch多纳尔

29

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

1
var filesToDelete = new DirectoryInfo(@“ C:\ Temp”)。GetFiles()。其中​​(x => x.LastAccessTime <DateTime.Now.AddMonths(-3)); //变化
Ta01 2010年

2
哇!除了我之外,还有其他人认为过度使用LINQ非常棒!;)
Filip Ekberg 2010年

.ToList()除了通过匹配文件进行第二次循环外,调用还添加了什么?
乔尔·穆勒

2
@乔尔·穆勒 List<T>定义了ForEach一种可用于将应用于Action<T>所有元素的方法。不幸的是,没有这样的扩展方法IEnumerable<T>
塞缪尔·内夫

1
好点子。我写我自己ForEach的扩展方法IEnumerable<T>是很久以前,我有时会忘记它没有内置的。
乔尔·穆勒

14

以下是如何获取目录中文件创建时间以及如何查找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[]
Dynami Le Sa​​vard

4
您应在foreach()循环外部声明一个新变量以保存的值(DateTime.Now- new TimeSpan(90, 0, 0, 0))。没有理由在循环中重复计算。
乍得


1

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



1

我已经尝试过此代码,并且效果很好,希望这个答案

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

2
90天<> 3个月
丹尼尔(Daniel)

1

想要在一定时间内删除文件的最典型方法是使用文件的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可能需要一个小时才能更新。




0
            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删除文件夹文件


0
         //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();
                }

            }

0

例如:要在源代码上进入“我的文件夹”项目,我需要打开两个文件夹。我将这种算法设置为每周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();
        }
    }

0

我在作为服务运行的控制台应用程序中使用以下命令,以从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();
                }
            }

        }

0

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;
          }

0

因为与解决方案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);
        }
    }
}

0

只需创建一个小的删除功能即可帮助您完成此任务,我已经测试了此代码,并且运行良好。

此功能可删除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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.