Xóa các tệp cũ hơn 3 tháng tuổi trong một thư mục bằng .NET


117

Tôi muốn biết (sử dụng C #) làm thế nào tôi có thể xóa các tệp trong một thư mục nhất định cũ hơn 3 tháng, nhưng tôi đoán khoảng thời gian ngày có thể linh hoạt.

Nói rõ hơn: Tôi đang tìm kiếm các tệp cũ hơn 90 ngày, nói cách khác, các tệp được tạo ít hơn 90 ngày trước nên được giữ lại, tất cả các tệp khác đã bị xóa.


Nếu có một lượng tệp quan trọng, tốt nhất là sử dụng Enum CảFiles và Enum CảDirectories thay vì GetFiles và GetDirectories, vì họ trực tiếp chạy bảng liệt kê thay vì thu thập danh sách. Tuy nhiên, bạn sẽ phải sử dụng một vòng lặp foreach.
Larry

Câu trả lời:


257

Một cái gì đó như thế này outta làm điều đó.

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

Cảm ơn, tôi nhận thấy bạn đang sử dụng lastAccessTime, đây có phải là thời gian tạo không?
JL.

10
không, như propertyNames nói: LastAccessTime- bạn nên đi lấy tài sản CreationTimenếu bạn muốn!
Andreas Niedermair

4
Vâng, tài sản bạn sử dụng là hoàn toàn tùy thuộc vào bạn. Bạn cũng có thể sử dụng LastWriteTime nếu bạn muốn.
Steve Danner

3
+1 để giúp tôi ra ngoài. Thay vì tạo một phiên bản FileInfo mới, bạn có thể sử dụng File.GetCreationTime hoặc File.GetLastAccessTime. Nên là một cải tiến hiệu suất nhỏ.
Mario Chiếc thìa

5
Tôi đoán GetFiles và Xóa không bao giờ thất bại trong môi trường của bạn? Chỉ cần chỉ ra rằng đây có vẻ là một câu trả lời rất được tham khảo.
Andrew Hagner

93

Đây là lambda 1 lớp:

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

@VladL Tôi nhận được "IEnumerable <FileInfo> không chứa ForEach" nếu tôi thả ToList (). Tôi chỉ giữ nó trong.
James Love

3
Tôi thích điều này. Nhưng tôi sẽ xóa phần xóa trong một lần thử / bắt
H20rider

new DirectoryInfo(dir).GetFiles() nhanh hơn new FileInfo(f) cho mỗi tập tin duy nhất.
Vojtěch Dohnal

29

Đối với những người thích sử dụng quá mức 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 (). Trong đó (x => x.LastAccessTime <DateTime.Now.AddMonths (-3)); // biến thể
Ta01

2
Ôi chao! Một người khác ngoài tôi nghĩ rằng việc sử dụng LINQ quá mức là tuyệt vời! ;)
Filip Ekberg

Không những gì .ToList()gọi thêm khác hơn là một vòng lặp thứ hai thông qua các tập tin phù hợp?
Joel Mueller

2
@Joel Mueller. List<T>định nghĩa một ForEachphương thức có thể được sử dụng để áp dụng Action<T>cho tất cả các phần tử. Thật không may, không có phương pháp mở rộng như vậy cho IEnumerable<T>.
Samuel Neff

1
Điểm tốt. Tôi đã viết ForEachphương thức mở rộng của riêng mình từ IEnumerable<T>rất lâu rồi, đôi khi tôi quên rằng nó không được tích hợp sẵn.
Joel Mueller

14

Đây là đoạn trích về cách lấy thời gian tạo tệp trong thư mục và tìm những tệp đã được tạo 3 tháng trước (chính xác là 90 ngày trước):

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

Không cần ToList(), DirectoryInfo.GetFiles()trả về a FileInfo[].
Dynami Le Savard

4
Bạn nên khai báo một biến mới bên ngoài foreach()vòng lặp để giữ giá trị của (DateTime.Now- new TimeSpan(90, 0, 0, 0)). Không có lý do để tính toán mà lặp đi lặp lại trong vòng lặp.
Chad


1

Về cơ bản, bạn có thể sử dụng Directory.Getfiles (Đường dẫn) để lấy danh sách tất cả các tệp. Sau đó, bạn lặp qua danh sách và gọi GetLastAccessTim () như Keith đề xuất.


1

Một cái gì đó như thế

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

1

Tôi đã thử mã này và nó hoạt động rất tốt, hy vọng điều này đã trả lời

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 ngày <> 3 tháng
Daniel

1

Cách tiếp cận kinh điển nhất khi muốn xóa các tệp trong một khoảng thời gian nhất định là sử dụng LastWriteTime của tệp (Lần cuối cùng tệp được sửa đổi):

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

(Trên đây dựa trên câu trả lời của Uri nhưng với LastWriteTime.)

Bất cứ khi nào bạn nghe thấy mọi người nói về việc xóa các tệp cũ hơn một khung thời gian nhất định (là một hoạt động khá phổ biến), thì việc thực hiện dựa trên LastModifiedTime của tệp hầu như luôn luôn là những gì họ đang tìm kiếm.

Ngoài ra, đối với những trường hợp rất bất thường, bạn có thể sử dụng những điều dưới đây, nhưng hãy cẩn thận khi sử dụng chúng.

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

Thời gian tập tin được tạo ở vị trí hiện tại. Tuy nhiên, hãy cẩn thận nếu tệp được sao chép, đó sẽ là thời gian nó được sao chép và CreationTimesẽ mới hơn tệp LastWriteTime.

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

Nếu bạn muốn xóa các tệp dựa trên lần đọc cuối cùng, bạn có thể sử dụng tệp này, nhưng không có gì đảm bảo nó sẽ được cập nhật vì nó có thể bị vô hiệu hóa trong NTFS. Kiểm tra fsutil behavior query DisableLastAccessxem nếu nó là trên. Ngoài ra, dưới NTFS, có thể mất tới một giờ để LastAccessTime của tệp cập nhật sau khi được truy cập.


0

bạn chỉ cần FileInfo -> CreationTime

và hơn là chỉ tính chênh lệch thời gian.

trong app.config bạn có thể lưu TimeSpan giá trị về độ tuổi của tệp phải bị xóa

đồng thời kiểm tra phép trừ DateTime phương pháp .

chúc may mắn



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

sử dụng trong tải trang hoặc dịch vụ web hoặc bất kỳ việc sử dụng nào khác.

Khái niệm của tôi là evrry 7 ngày tôi phải xóa tập tin thư mục mà không sử dụng 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

Ví dụ: Để đi dự án thư mục của tôi trên nguồn, tôi cần lên hai thư mục. Tôi thực hiện algorim này đến 2 ngày trong tuần và thành bốn giờ

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

Tôi sử dụng thông tin sau trong ứng dụng bảng điều khiển, chạy dưới dạng dịch vụ, để lấy thông tin thư mục từ tệp App.Sinstall. Số ngày để giữ các tệp cũng có thể định cấu hình, nhân với -1 để sử dụng trong phương thức AddDays () của DateTime.Now.

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

Một loại ví dụ SSIS .. (nếu điều này giúp được bất cứ ai)

          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

kể từ khi giải pháp với new FileInfo(filePath)không dễ dàng kiểm chứng, tôi đề nghị sử dụng đóng gói cho các lớp học như Directory, FilePathnhư thế này:

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

Sau đó sử dụng một cái gì đó như thế này:

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

Chỉ cần tạo một chức năng xóa nhỏ có thể giúp bạn đạt được nhiệm vụ này, tôi đã kiểm tra mã này và nó chạy hoàn toàn tốt.

Hàm này xóa các tệp cũ hơn 90 ngày cũng như một tệp có đuôi .zip sẽ bị xóa khỏi thư mục.

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.