Supprimer les fichiers de plus de 3 mois dans un répertoire à l'aide de .NET

119

Je voudrais savoir (en utilisant C #) comment je peux supprimer des fichiers dans un certain répertoire datant de plus de 3 mois, mais je suppose que la période de date pourrait être flexible.

Juste pour être clair: je recherche des fichiers datant de plus de 90 jours, c'est-à-dire que les fichiers créés il y a moins de 90 jours doivent être conservés, tous les autres supprimés.

JL.
la source
S'il existe un nombre important de fichiers, le mieux est d'utiliser EnumerateFiles et EnumerateDirectories au lieu de GetFiles et GetDirectories, car ils exécutent directement l'énumération au lieu de rassembler une liste. Cependant, vous devrez utiliser une boucle foreach.
Larry

Réponses:

258

Quelque chose comme ça ne le fait pas.

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
la source
Merci, j'ai remarqué que vous utilisez lastAccessTime, est-ce le moment de la création?
JL.
10
non, comme le dit propertyNames: LastAccessTime- vous devriez opter pour la propriété CreationTimesi vous le souhaitez!
Andreas Niedermair
4
Ouais, quelle propriété que vous utilisez dépend entièrement de vous. Vous pouvez également utiliser LastWriteTime si vous le souhaitez.
Steve Danner
3
+1 pour m'avoir aidé. Au lieu de créer une nouvelle instance FileInfo, vous pouvez utiliser File.GetCreationTime ou File.GetLastAccessTime. Devrait être une amélioration mineure des performances.
Mario The Spoon
5
Je suppose que GetFiles et Delete n'échouent jamais dans votre environnement? Il suffit de souligner cela, car cela semble être une réponse hautement référencée.
Andrew Hagner
93

Voici un 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
la source
@VladL J'obtiens un "IEnumerable <FileInfo> ne contient pas ForEach" si je laisse tomber le ToList (). Je viens de le garder.
James Love
3
J'aime ça. Mais je envelopperais la suppression dans un essai / capture
H20rider
new DirectoryInfo(dir).GetFiles()est plus rapide que new FileInfo(f)pour chaque fichier.
Vojtěch Dohnal
29

Pour ceux qui aiment surutiliser 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());
Samuel Neff
la source
1
var filesToDelete = new DirectoryInfo (@ "C: \ Temp"). GetFiles (). Where (x => x.LastAccessTime <DateTime.Now.AddMonths (-3)); // variation
Ta01
2
Woho! Quelqu'un d'autre que moi pense que l'utilisation excessive de LINQ est géniale! ;)
Filip Ekberg
Qu'est-ce que l' .ToList()appel ajoute à part une deuxième boucle dans les fichiers correspondants?
Joel Mueller
2
@Joel Mueller. List<T>définit une ForEachméthode qui peut être utilisée pour appliquer un Action<T>à tous les éléments. Malheureusement, il n'existe pas de méthode d'extension pour les fichiers IEnumerable<T>.
Samuel Neff
1
Bon point. J'ai écrit ma propre ForEachméthode d'extension IEnumerable<T>il y a si longtemps, j'oublie parfois qu'elle n'est pas intégrée.
Joel Mueller
14

Voici un extrait de la façon d'obtenir l'heure de création des fichiers dans le répertoire et de trouver ceux qui ont été créés il y a 3 mois (il y a 90 jours pour être exact):

    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
la source
Pas besoin de ToList(), DirectoryInfo.GetFiles()retourne a FileInfo[].
Dynami Le Savard
4
Vous devez déclarer une nouvelle variable en dehors de la foreach()boucle pour contenir la valeur de (DateTime.Now- new TimeSpan(90, 0, 0, 0)). Il n'y a aucune raison de calculer cela à plusieurs reprises dans la boucle.
Tchad
1

En gros, vous pouvez utiliser Directory.Getfiles (Path) pour obtenir une liste de tous les fichiers. Après cela, vous parcourez la liste et appelez GetLastAccessTim () comme Keith l'a suggéré.

Ian Jacobs
la source
1

Quelque chose comme ca

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

J'ai essayé ce code et cela fonctionne très bien, j'espère que cela répondra

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
la source
2
90 jours <> 3 mois
Daniel
1

L'approche la plus canonique lorsque vous souhaitez supprimer des fichiers sur une certaine durée consiste à utiliser LastWriteTime du fichier (dernière fois que le fichier a été modifié):

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

(Ce qui précède est basé sur la réponse d'Uri mais avec LastWriteTime.)

Chaque fois que vous entendez des gens parler de la suppression de fichiers plus anciens qu'une certaine période (ce qui est une activité assez courante), le faire en fonction de LastModifiedTime du fichier est presque toujours ce qu'ils recherchent.

Sinon, dans des circonstances très inhabituelles, vous pouvez utiliser les éléments ci-dessous, mais utilisez-les avec prudence car ils comportent des mises en garde.

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

L'heure à laquelle le fichier a été créé à l'emplacement actuel. Cependant, faites attention si le fichier a été copié, ce sera l'heure à laquelle il a été copié et CreationTimesera plus récent que celui du fichier LastWriteTime.

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

Si vous souhaitez supprimer les fichiers en fonction de la dernière fois qu'ils ont été lus, vous pouvez l'utiliser, mais il n'y a aucune garantie qu'il sera mis à jour car il peut être désactivé dans NTFS. Vérifiez fsutil behavior query DisableLastAccesss'il est activé. Sous NTFS également, la mise à jour de LastAccessTime du fichier peut prendre jusqu'à une heure après son accès.

Tolga
la source
0

vous avez juste besoin de FileInfo -> CreationTime

et que de simplement calculer le décalage horaire.

dans l'app.config, vous pouvez enregistrer la valeur TimeSpan de l'âge du fichier à supprimer

consultez également la méthode DateTime Subtract .

bonne chance

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

utilisation dans le chargement de page ou le service Web ou toute autre utilisation.

Mon concept est tous les 7 jours que je dois supprimer le fichier de dossier sans utiliser DB

vishal
la source
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
la source
0

Par exemple: pour accéder à mon projet de dossier sur la source, j'ai besoin de deux dossiers. Je fais cet algorim en 2 jours par semaine et en 4 heures

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
la source
0

J'utilise ce qui suit dans une application console, exécutée en tant que service, pour obtenir des informations de répertoire à partir du fichier App.Settings. Le nombre de jours pour conserver les fichiers est également configurable, multiplié par -1 pour une utilisation dans la méthode AddDays () de 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
la source
0

Un exemple de type SSIS ... (si cela aide quelqu'un)

          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
la source
0

comme les solutions avec new FileInfo(filePath)ne sont pas facilement testables, je suggère d'utiliser des Wrappers pour des classes comme Directory, Fileet Pathcomme ceci:

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

Ensuite, utilisez quelque chose comme ceci:

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
la source
0

Créez simplement une petite fonction de suppression qui peut vous aider à réaliser cette tâche, j'ai testé ce code et il fonctionne parfaitement bien.

Cette fonction supprime les fichiers datant de plus de 90 jours ainsi qu'un fichier avec l'extension .zip à supprimer d'un dossier.

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
la source