Löschen Sie mit .NET Dateien, die älter als 3 Monate sind, in einem Verzeichnis

117

Ich würde gerne wissen (mit C #), wie ich Dateien in einem bestimmten Verzeichnis löschen kann, das älter als 3 Monate ist, aber ich denke, der Datumszeitraum könnte flexibel sein.

Um ganz klar zu sein: Ich suche nach Dateien, die älter als 90 Tage sind, dh Dateien, die vor weniger als 90 Tagen erstellt wurden, sollten aufbewahrt und alle anderen gelöscht werden.

J L.
quelle
Wenn eine große Anzahl von Dateien vorhanden ist, verwenden Sie am besten EnumerateFiles und EnumerateDirectories anstelle von GetFiles und GetDirectories, da diese die Enumeration direkt ausführen, anstatt eine Liste zu erstellen. Sie müssen jedoch eine foreach-Schleife verwenden.
Larry

Antworten:

257

So etwas macht es nicht.

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
quelle
Vielen Dank, ich habe festgestellt, dass Sie lastAccessTime verwenden. Ist dies die Erstellungszeit?
JL.
10
Nein, wie propertyNames sagt: LastAccessTime- Sie sollten sich für eine Immobilie entscheiden, CreationTimewenn Sie möchten!
Andreas Niedermair
4
Ja, welche Eigenschaft Sie verwenden, liegt ganz bei Ihnen. Sie können auch LastWriteTime verwenden, wenn Sie möchten.
Steve Danner
3
+1 für meine Hilfe. Anstatt eine neue FileInfo-Instanz zu erstellen, können Sie File.GetCreationTime oder File.GetLastAccessTime verwenden. Sollte eine geringfügige Leistungsverbesserung sein.
Mario The Spoon
5
Ich denke, GetFiles und Delete scheitern nie in Ihrer Umgebung? Ich möchte nur darauf hinweisen, da dies eine sehr referenzierte Antwort zu sein scheint.
Andrew Hagner
93

Hier ist ein 1-Liner-Lambda:

Directory.GetFiles(dirName)
         .Select(f => new FileInfo(f))
         .Where(f => f.LastAccessTime < DateTime.Now.AddMonths(-3))
         .ToList()
         .ForEach(f => f.Delete());
Uri Abramson
quelle
@VladL Ich erhalte eine "IEnumerable <FileInfo> enthält kein ForEach", wenn ich die ToList () lösche. Ich habe es einfach behalten.
James Love
3
Ich mag das. Aber ich würde das Löschen in einen Versuch / Fang
einwickeln
new DirectoryInfo(dir).GetFiles()ist schneller als new FileInfo(f)für jede einzelne Datei.
Vojtěch Dohnal
29

Für diejenigen, die LINQ gerne überbeanspruchen.

(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
quelle
1
var filesToDelete = new DirectoryInfo (@ "C: \ Temp"). GetFiles (). Where (x => x.LastAccessTime <DateTime.Now.AddMonths (-3)); // Variation
Ta01
2
Woho! Jemand anders als ich findet die Überbeanspruchung von LINQ großartig! ;)
Filip Ekberg
Was fügt der .ToList()Aufruf außer einer zweiten Schleife durch die übereinstimmenden Dateien hinzu?
Joel Mueller
2
@ Joel Mueller. List<T>definiert eine ForEachMethode, mit der eine Action<T>auf alle Elemente angewendet werden kann . Leider gibt es keine solche Erweiterungsmethode für IEnumerable<T>.
Samuel Neff
1
Guter Punkt. Ich habe meine eigene ForEachErweiterungsmethode vor IEnumerable<T>so langer Zeit geschrieben, dass ich manchmal vergesse, dass sie nicht eingebaut ist.
Joel Mueller
14

Hier ist ein Ausschnitt davon, wie Sie die Erstellungszeit von Dateien im Verzeichnis ermitteln und diejenigen finden, die vor 3 Monaten (genauer gesagt vor 90 Tagen) erstellt wurden:

    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
quelle
Keine Notwendigkeit für ToList(), DirectoryInfo.GetFiles()gibt a zurück FileInfo[].
Dynami Le Savard
4
Sie sollten eine neue Variable außerhalb der foreach()Schleife deklarieren , um den Wert von zu speichern (DateTime.Now- new TimeSpan(90, 0, 0, 0)). Es gibt keinen Grund, dies wiederholt in der Schleife zu berechnen.
Tschad
1

Grundsätzlich können Sie Directory.Getfiles (Pfad) verwenden, um eine Liste aller Dateien abzurufen. Danach durchlaufen Sie die Liste und rufen GetLastAccessTim () auf, wie Keith vorgeschlagen hat.

Ian Jacobs
quelle
1

Sowas in der Art

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

Ich habe diesen Code ausprobiert und er funktioniert sehr gut. Ich hoffe, dies wurde beantwortet

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
quelle
2
90 Tage <> 3 Monate
Daniel
1

Der kanonischste Ansatz beim Löschen von Dateien über einen bestimmten Zeitraum ist die Verwendung von LastWriteTime (das letzte Mal, als die Datei geändert wurde):

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

(Das obige basiert auf Uris Antwort, aber mit LastWriteTime.)

Wenn Sie Leute über das Löschen von Dateien sprechen hören, die älter als ein bestimmter Zeitraum sind (was eine ziemlich häufige Aktivität ist), ist es fast immer das, wonach sie suchen, wenn sie auf der LastModifiedTime der Datei basieren.

Alternativ können Sie unter sehr ungewöhnlichen Umständen die folgenden Optionen verwenden. Verwenden Sie diese jedoch mit Vorsicht, da sie mit Einschränkungen verbunden sind.

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

Die Zeit, zu der die Datei am aktuellen Speicherort erstellt wurde. Seien Sie jedoch vorsichtig, wenn die Datei kopiert wurde. Dies ist die Zeit, zu der sie kopiert wurde, und CreationTimesie ist neuer als die Datei LastWriteTime.

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

Wenn Sie die Dateien basierend auf dem letzten Lesevorgang löschen möchten, können Sie dies verwenden. Es gibt jedoch keine Garantie dafür, dass sie aktualisiert werden, da sie in NTFS deaktiviert werden können. Überprüfen Sie fsutil behavior query DisableLastAccess, ob es eingeschaltet ist. Auch unter NTFS kann es bis zu einer Stunde dauern, bis die LastAccessTime der Datei nach dem Zugriff aktualisiert wird.

Tolga
quelle
0

Sie brauchen nur FileInfo -> CreationTime

und dann nur die Zeitdifferenz berechnen.

In der app.config können Sie den TimeSpan- Wert speichern , wie alt die Datei sein muss, um gelöscht zu werden

Schauen Sie sich auch die DateTime Subtract- Methode an.

Viel Glück

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

Verwendung beim Laden von Seiten oder im Webservice oder bei jeder anderen Verwendung.

Mein Konzept ist alle 7 Tage, an denen ich Ordnerdateien löschen muss, ohne DB zu verwenden

vishal
quelle
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
quelle
0

Zum Beispiel: Um Mein Ordnerprojekt auf Quelle zu gehen, muss ich zwei Ordner aufrüsten. Ich mache diesen Algorithmus zu 2 Tagen in der Woche und in vier Stunden

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
quelle
0

Ich verwende Folgendes in einer Konsolen-App, die als Dienst ausgeführt wird, um Verzeichnisinformationen aus der App.Settings-Datei abzurufen. Die Anzahl der Tage, an denen die Dateien aufbewahrt werden sollen, kann ebenfalls konfiguriert und mit -1 multipliziert werden, um sie in der AddDays () -Methode von DateTime.Now zu verwenden.

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
quelle
0

Ein Beispiel vom Typ SSIS. (Wenn dies jemandem hilft)

          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.
quelle
0

da die Lösungen mit new FileInfo(filePath)nicht leicht überprüfbar sind, schlage ich Wrappers wie für die Klassen zu verwenden Directory, Fileund Pathwie folgt aus :

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

Dann benutze so etwas:

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
quelle
0

Erstellen Sie einfach eine kleine Löschfunktion, die Ihnen bei der Erfüllung dieser Aufgabe helfen kann. Ich habe diesen Code getestet und er läuft einwandfrei.

Diese Funktion löscht Dateien, die älter als 90 Tage sind , sowie eine Datei mit der Erweiterung .zip , die aus einem Ordner gelöscht werden soll.

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
quelle