Hapus file yang berusia lebih dari 3 bulan di direktori menggunakan .NET

118

Saya ingin tahu (menggunakan C #) bagaimana saya bisa menghapus file di direktori tertentu yang lebih tua dari 3 bulan, tapi saya rasa periode tanggal bisa fleksibel.

Hanya untuk memperjelas: Saya mencari file yang lebih lama dari 90 hari, dengan kata lain file yang dibuat kurang dari 90 hari yang lalu harus disimpan, semua yang lain dihapus.

JL.
sumber
Jika ada sejumlah besar file, yang terbaik adalah menggunakan EnumerateFiles dan EnumerateDirectories alih-alih GetFiles dan GetDirectories, karena mereka secara langsung menjalankan enumerasi alih-alih mengumpulkan daftar. Namun, Anda harus menggunakan foreach loop.
Larry

Jawaban:

258

Sesuatu seperti ini akan berhasil.

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();
}
Steve Danner
sumber
Terima kasih, saya perhatikan Anda menggunakan lastAccessTime, apakah ini waktu pembuatan?
JL.
10
tidak, seperti yang dikatakan propertyNames: LastAccessTime- Anda harus mencari properti CreationTimejika Anda mau!
Andreas Niedermair
4
Ya, properti mana yang Anda gunakan sepenuhnya terserah Anda. Anda juga bisa menggunakan LastWriteTime jika Anda mau.
Steve Danner
3
1 untuk membantu saya. Alih-alih membuat instance FileInfo baru, Anda dapat menggunakan File.GetCreationTime atau File.GetLastAccessTime. Harus ada peningkatan kinerja kecil.
Mario The Spoon
5
Saya kira GetFiles dan Delete tidak pernah gagal di lingkungan Anda? Hanya menunjukkan itu karena ini sepertinya jawaban yang sangat direferensikan.
Andrew Hagner
93

Ini lambda 1-liner:

Directory.GetFiles(dirName)
         .Select(f => new FileInfo(f))
         .Where(f => f.LastAccessTime < DateTime.Now.AddMonths(-3))
         .ToList()
         .ForEach(f => f.Delete());
Uri Abramson
sumber
@VladL Saya mendapatkan "IEnumerable <FileInfo> tidak berisi ForEach" jika saya menjatuhkan ToList (). Aku hanya menyimpannya.
James Love
3
Saya suka ini. Tapi saya akan membungkus penghapusan dalam mencoba / menangkap
H20rider
new DirectoryInfo(dir).GetFiles()lebih cepat daripada new FileInfo(f)untuk setiap file.
Vojtěch Dohnal
29

Bagi mereka yang suka menggunakan LINQ secara berlebihan.

(from f in new DirectoryInfo("C:/Temp").GetFiles()
 where f.CreationTime < DateTime.Now.Subtract(TimeSpan.FromDays(90))
 select f
).ToList()
    .ForEach(f => f.Delete());
Samuel Neff
sumber
1
var filesToDelete = new DirectoryInfo (@ "C: \ Temp"). GetFiles (). Dimana (x => x.LastAccessTime <DateTime.Now.AddMonths (-3)); // variasi
Ta01
2
Woho! Orang lain selain saya menganggap penggunaan LINQ secara berlebihan itu luar biasa! ;)
Filip Ekberg
Apa .ToList()panggilan menambahkan selain loop kedua melalui file yang cocok?
Joel Mueller
2
@Joel Mueller. List<T>mendefinisikan ForEachmetode yang dapat digunakan untuk menerapkan Action<T>ke semua elemen. Sayangnya tidak ada metode ekstensi seperti itu untuk IEnumerable<T>.
Samuel Neff
1
Poin yang bagus. Saya sudah lama menulis ForEachmetode ekstensi saya sendiri IEnumerable<T>, terkadang saya lupa metode ini tidak ada di dalamnya.
Joel Mueller
14

Berikut adalah cuplikan cara mendapatkan waktu pembuatan file di direktori dan menemukan yang telah dibuat 3 bulan yang lalu (tepatnya 90 hari yang lalu):

    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();
        }
    }
Pierre-Luc Champigny
sumber
Tidak perlu ToList(), DirectoryInfo.GetFiles()mengembalikan a FileInfo[].
Dynami Le Savard
4
Anda harus mendeklarasikan variabel baru di luar foreach()loop untuk menampung nilai (DateTime.Now- new TimeSpan(90, 0, 0, 0)). Tidak ada alasan untuk menghitungnya berulang kali dalam loop.
Chad
1

Pada dasarnya Anda dapat menggunakan Directory.Getfiles (Path) untuk mendapatkan daftar semua file. Setelah itu Anda mengulang daftar dan memanggil GetLastAccessTim () seperti yang disarankan Keith.

Ian Jacobs
sumber
1

Sesuatu seperti itu

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

saya telah mencoba kode ini dan bekerja dengan sangat baik, semoga ini dijawab

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();
        }
    }
}
Rosidin Bima
sumber
2
90 hari <> 3 bulan
Daniel
1

Pendekatan paling kanonik ketika ingin menghapus file selama durasi tertentu adalah dengan menggunakan LastWriteTime file (Terakhir kali file diubah):

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

(Di atas berdasarkan jawaban Uri tetapi dengan LastWriteTime.)

Setiap kali Anda mendengar orang berbicara tentang menghapus file yang lebih lama dari kerangka waktu tertentu (yang merupakan aktivitas yang cukup umum), melakukannya berdasarkan LastModifiedTime file hampir selalu apa yang mereka cari.

Alternatifnya, untuk keadaan yang sangat tidak biasa Anda dapat menggunakan yang di bawah ini, tetapi gunakan ini dengan hati-hati karena disertai peringatan.

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

Waktu file dibuat di lokasi saat ini. Namun, berhati-hatilah jika file disalin, itu akan menjadi waktu yang disalin dan CreationTimeakan lebih baru dari file itu LastWriteTime.

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

Jika Anda ingin menghapus file berdasarkan terakhir kali mereka dibaca, Anda dapat menggunakan ini, tetapi tidak ada jaminan akan diperbarui karena dapat dinonaktifkan di NTFS. Periksa fsutil behavior query DisableLastAccessuntuk melihat apakah sudah aktif. Juga di bawah NTFS mungkin membutuhkan waktu hingga satu jam untuk LastAccessTime file untuk memperbarui setelah itu diakses.

Tolga
sumber
0

Anda hanya perlu FileInfo -> CreationTime

dan dari sekadar menghitung perbedaan waktu.

di app.config Anda dapat menyimpan nilai TimeSpan dari berapa lama file harus dihapus

periksa juga metode Kurangi DateTime .

semoga berhasil

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

digunakan dalam pemuatan halaman atau layanan web atau penggunaan lainnya.

Konsep saya evrry 7 hari saya harus menghapus file folder tanpa menggunakan DB

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

            }
Arihant Lodha
sumber
0

Misalnya: Untuk membuka proyek folder saya di sumber, saya perlu membuka dua folder. Saya membuat algorim ini menjadi 2 hari seminggu dan menjadi empat jam

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();
        }
    }
Maximiliano Cesán
sumber
0

Saya menggunakan berikut ini di aplikasi konsol, menjalankan sebagai layanan, untuk mendapatkan info direktori dari file App.Settings. Jumlah hari untuk menyimpan file juga dapat dikonfigurasi, dikalikan dengan -1 untuk digunakan dalam metode AddDays () dari 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();
                }
            }

        }
n122vu
sumber
0

Contoh jenis SSIS .. (jika ini membantu siapa pun)

          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;
          }
Allan F
sumber
0

karena solusi dengan new FileInfo(filePath)tidak mudah diuji, saya sarankan untuk menggunakan Wrappers untuk kelas seperti Directory, Filedan Pathseperti ini:

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

Kemudian gunakan sesuatu seperti ini:

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);
        }
    }
}
MovGP0
sumber
0

Buat saja fungsi hapus kecil yang dapat membantu Anda mencapai tugas ini, saya telah menguji kode ini dan itu berjalan dengan baik.

Fungsi ini menghapus file yang lebih lama dari 90 hari serta file dengan ekstensi .zip untuk dihapus dari folder.

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
Rachit Rastogi
sumber