.NET kullanarak bir dizinde 3 aydan daha eski dosyaları silin


118

3 aydan daha eski belirli bir dizindeki dosyaları nasıl silebileceğimi (C # kullanarak) bilmek istiyorum, ancak tarih periyodu esnek olabilir.

Açık olmak gerekirse: 90 günden eski dosyalar arıyorum, diğer bir deyişle 90 günden daha kısa süre önce oluşturulan dosyalar saklanmalı, diğerleri silinmelidir.


Önemli miktarda dosya varsa, en iyisi GetFiles ve GetDirectories yerine EnumerateFiles ve EnumerateDirectories kullanmaktır, çünkü bunlar liste toplamak yerine doğrudan numaralandırmayı çalıştırırlar. Ancak, bir foreach döngüsü kullanmanız gerekecek.
Larry

Yanıtlar:


258

Bunun gibi bir şey yapamaz.

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

Teşekkürler, lastAccessTime kullandığınızı fark ettim, bu oluşturma zamanı mı?
JL.

10
hayır, propertyNames'in dediği gibi: LastAccessTime- isterseniz mülk için gitmelisiniz CreationTime!
Andreas Niedermair 08

4
Evet, hangi mülkü kullanacağın tamamen sana bağlı. İsterseniz LastWriteTime'ı da kullanabilirsiniz.
Steve Danner

3
Bana yardım ettiğin için +1. Yeni bir FileInfo örneği oluşturmak yerine File.GetCreationTime veya File.GetLastAccessTime kullanabilirsiniz. Küçük bir performans iyileştirmesi olmalı.
Mario The Spoon

5
Sanırım GetFiles ve Delete ortamınızda asla başarısız olmaz mı? Sadece buna dikkat çekiyorum, çünkü bu çok referanslı bir cevap gibi görünüyor.
Andrew Hagner

93

İşte 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 () 'i bırakırsam "IEnumerable <FileInfo> ForEach içermiyor" mesajı alıyorum. Sadece içeride tuttum.
James Love

3
Bunu severim. Ama silme işlemini bir dene / yakala ile
sarardım

new DirectoryInfo(dir).GetFiles()new FileInfo(f)her bir dosyadan daha hızlıdır .
Vojtěch Dohnal

29

LINQ'yu aşırı kullanmayı sevenler için.

(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 (). Burada (x => x.LastAccessTime <DateTime.Now.AddMonths (-3)); // varyasyon
Ta01

2
Woho! Benden başka biri LINQ kullanımının harika olduğunu düşünüyor! ;)
Filip Ekberg

.ToList()Çağrı, eşleşen dosyalar arasında ikinci bir döngüden başka ne ekler?
Joel Mueller

2
@Joel Mueller. tüm elemanlara bir uygulamak için kullanılabilecek List<T>bir ForEachyöntemi tanımlar Action<T>. Ne yazık ki için böyle bir uzatma yöntemi yok IEnumerable<T>.
Samuel Neff

1
İyi bir nokta. Kendi ForEachuzatma yöntemimi IEnumerable<T>çok uzun zaman önce yazmıştım , bazen yerleşik olmadığını unutuyorum.
Joel Mueller

14

Dizindeki dosyaların oluşturulma zamanının nasıl alınacağına ve 3 ay önce (tam olarak 90 gün önce) oluşturulmuş olanların nasıl bulunacağına dair bir pasaj:

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

Gerek yok ToList(), DirectoryInfo.GetFiles()döndürür a FileInfo[].
dynami Le Savard

4
foreach()Değerini tutmak için döngünün dışında yeni bir değişken tanımlamalısınız (DateTime.Now- new TimeSpan(90, 0, 0, 0)). Bunu döngüde tekrar tekrar hesaplamak için hiçbir neden yok.
Çad


1

Temel olarak, tüm dosyaların bir listesini almak için Directory.Getfiles (Yol) öğesini kullanabilirsiniz. Bundan sonra listeyi gözden geçirin ve Keith'in önerdiği gibi GetLastAccessTim () 'i çağırın.


1

Bunun gibi bir şey

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

1

bu kodu denedim ve çok iyi çalışıyor, umarım bu cevap

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 gün <> 3 ay
Daniel

1

Dosyaları belirli bir süre boyunca silmek istediğinizde en kanonik yaklaşım, dosyanın LastWriteTime (dosyanın en son değiştirildiği zaman) kullanmaktır:

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

(Yukarıdakiler Uri'nin cevabına dayanmaktadır, ancak ile LastWriteTime.)

İnsanların belirli bir zaman diliminden daha eski dosyaları silmekten bahsettiklerini duyduğunuzda (ki bu oldukça yaygın bir etkinliktir), bunu dosyanın LastModifiedTime temelinde yapmak neredeyse her zaman aradıkları şeydir.

Alternatif olarak, çok sıra dışı durumlar için aşağıdakileri kullanabilirsiniz, ancak uyarılarla birlikte geldiklerinden bunları dikkatli kullanın.

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

Dosyanın mevcut konumda oluşturulduğu saat. Ancak, dosya kopyalandıysa dikkatli olun, kopyalandığı zaman CreationTimeolacak ve dosyadan daha yeni olacaktır LastWriteTime.

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

Dosyaları en son okundukları zamana göre silmek isterseniz bunu kullanabilirsiniz, ancak NTFS'de devre dışı bırakılabileceği için güncelleneceğine dair bir garanti yoktur. Açık fsutil behavior query DisableLastAccessolup olmadığını kontrol edin . Ayrıca NTFS altında, dosyaya erişildikten sonra LastAccessTime'ın güncellenmesi bir saat kadar sürebilir.




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

sayfa yüklemede veya web hizmetinde veya başka herhangi bir kullanımda kullanım.

Konseptim evrry 7 gündür DB kullanmadan klasör dosyasını silmem gerekiyor


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

Örneğin: Klasör projem kaynağa gitmek için iki klasöre ihtiyacım var. Bu algoritmayı haftada 2 gün ve dört saat olarak yapıyorum

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

Aşağıdakileri, bir hizmet olarak çalışan bir konsol uygulamasında, App.Settings dosyasından dizin bilgilerini almak için kullanıyorum. Dosyaların tutulacağı gün sayısı da yapılandırılabilir ve DateTime.Now'un AddDays () yönteminde kullanılmak üzere -1 ile çarpılır.

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 tipi bir örnek .. (eğer bu herkese yardımcı oluyorsa)

          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

ile çözümler beri new FileInfo(filePath)kolaylıkla test edilebilir değildir, ben gibi sınıflar için Wrappers kullanmak önermek Directory, Fileve Pathbunun gibi:

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

O zaman bunun gibi bir şey kullanın:

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

Sadece bu görevi gerçekleştirmenize yardımcı olabilecek küçük bir silme işlevi oluşturun, bu kodu test ettim ve mükemmel bir şekilde çalışıyor.

Bu işlev, 90 günden daha eski dosyaları ve bir klasörden silinecek .zip uzantılı bir dosyayı siler .

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.