Elimina i file più vecchi di 3 mesi in una directory utilizzando .NET


118

Vorrei sapere (usando C #) come posso eliminare i file in una determinata directory più vecchi di 3 mesi, ma immagino che il periodo di data potrebbe essere flessibile.

Giusto per essere chiari: cerco file più vecchi di 90 giorni, in altre parole i file creati meno di 90 giorni fa devono essere conservati, tutti gli altri eliminati.


Se è presente una quantità importante di file, la cosa migliore è utilizzare EnumerateFiles ed EnumerateDirectories invece di GetFiles e GetDirectories, perché eseguono direttamente l'enumerazione invece di raccogliere un elenco. Tuttavia, dovrai utilizzare un ciclo foreach.
Larry

Risposte:


258

Qualcosa di simile non lo fa.

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

Grazie, ho notato che stai usando lastAccessTime, è l'ora della creazione?
JL.

10
no, come dice propertyNames: LastAccessTime- dovresti scegliere proprietà CreationTimese lo desideri!
Andreas Niedermair

4
Sì, la proprietà che usi dipende interamente da te. Puoi anche usare LastWriteTime se lo desideri.
Steve Danner

3
+1 per avermi aiutato. Invece di creare una nuova istanza FileInfo, potresti usare File.GetCreationTime o File.GetLastAccessTime. Dovrebbe essere un lieve miglioramento delle prestazioni.
Mario The Spoon

5
Immagino che GetFiles e Delete non falliscano mai nel tuo ambiente? Faccio solo notare che questa sembra essere una risposta altamente referenziata.
Andrew Hagner

93

Ecco un lambda a 1 riga:

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

@VladL ottengo un "IEnumerable <FileInfo> non contiene ForEach" se elimino ToList (). L'ho solo tenuto.
James Love

3
Mi piace questo. Ma vorrei racchiudere l'eliminazione in una prova / cattura
H20rider

new DirectoryInfo(dir).GetFiles()è più veloce che new FileInfo(f)per ogni singolo file.
Vojtěch Dohnal

29

Per coloro a cui piace utilizzare 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 (). Where (x => x.LastAccessTime <DateTime.Now.AddMonths (-3)); // variazione
Ta01

2
Woho! Qualcun altro oltre a me pensa che l'uso eccessivo di LINQ sia fantastico! ;)
Filip Ekberg

Cosa .ToList()aggiunge la chiamata oltre a un secondo ciclo attraverso i file corrispondenti?
Joel Mueller

2
@ Joel Mueller. List<T>definisce un ForEachmetodo che può essere utilizzato per applicare un Action<T>a tutti gli elementi. Sfortunatamente non esiste un tale metodo di estensione per IEnumerable<T>.
Samuel Neff

1
Buon punto. Ho scritto il mio ForEachmetodo di estensione IEnumerable<T>molto tempo fa, a volte dimentico che non è integrato.
Joel Mueller

14

Ecco uno snippet di come ottenere l'ora di creazione dei file nella directory e trovare quelli che sono stati creati 3 mesi fa (90 giorni fa per l'esattezza):

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

Non è necessario ToList(), DirectoryInfo.GetFiles()restituisce un file FileInfo[].
Dynami Le Savard

4
È necessario dichiarare una nuova variabile all'esterno del foreach()ciclo per contenere il valore di (DateTime.Now- new TimeSpan(90, 0, 0, 0)). Non c'è motivo di calcolarlo ripetutamente nel ciclo.
Ciad


1

Fondamentalmente puoi usare Directory.Getfiles (Path) per ottenere un elenco di tutti i file. Dopodiché, scorri l'elenco e chiami GetLastAccessTim () come suggerito da Keith.


1

Qualcosa del genere

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

1

ho provato questo codice e funziona molto bene, spero che questo abbia risposto

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 giorni <> 3 mesi
Daniel

1

L'approccio più canonico quando si desidera eliminare i file per una certa durata è utilizzare LastWriteTime del file (l'ultima volta che il file è stato modificato):

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

(Quanto sopra basato sulla risposta di Uri ma con LastWriteTime.)

Ogni volta che senti persone parlare di eliminare file più vecchi di un certo periodo di tempo (che è un'attività piuttosto comune), farlo in base al LastModifiedTime del file è quasi sempre quello che stanno cercando.

In alternativa, per circostanze molto insolite è possibile utilizzare quanto segue, ma utilizzarli con cautela poiché vengono forniti con avvertenze.

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

L'ora in cui il file è stato creato nella posizione corrente. Tuttavia, fai attenzione se il file è stato copiato, sarà l'ora in cui è stato copiato e CreationTimesarà più recente di quello del file LastWriteTime.

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

Se si desidera eliminare i file in base all'ultima volta che sono stati letti, è possibile utilizzarlo, ma non è garantito che verrà aggiornato poiché può essere disabilitato in NTFS. Controlla fsutil behavior query DisableLastAccessse è acceso. Inoltre, in NTFS, potrebbe essere necessaria fino a un'ora per l'aggiornamento di LastAccessTime del file dopo l'accesso.


0

hai solo bisogno di FileInfo -> CreationTime

e non solo calcolare la differenza di orario.

in app.config è possibile salvare il valore TimeSpan di quanti anni deve avere il file per essere cancellato

controlla anche il metodo DateTime Subtract .

in bocca al lupo



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

utilizzare nel caricamento della pagina o nel servizio web o qualsiasi altro uso.

Il mio concetto è evrry 7 giorni devo eliminare il file della cartella senza utilizzare 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

Ad esempio: per passare al progetto della mia cartella sull'origine, ho bisogno di due cartelle. Faccio questo algoritmo a 2 giorni alla settimana e in quattro ore

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

Uso quanto segue in un'app console, in esecuzione come servizio, per ottenere informazioni sulla directory dal file App.Settings. È anche possibile configurare il numero di giorni per la conservazione dei file, moltiplicato per -1 per l'utilizzo nel metodo AddDays () di 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

Un tipo di esempio SSIS .. (se questo aiuta qualcuno)

          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

poiché le soluzioni con new FileInfo(filePath)non sono facilmente testabili, suggerisco di utilizzare wrapper per classi come Directory, Filee Pathcome questa:

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

Quindi usa qualcosa del genere:

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

Basta creare una piccola funzione di cancellazione che possa aiutarti a raggiungere questo compito, ho testato questo codice e funziona perfettamente.

Questa funzione elimina i file più vecchi di 90 giorni e un file con estensione .zip da eliminare da una cartella.

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.