Удалите файлы старше 3 месяцев в каталоге с помощью .NET

119

Я хотел бы знать (используя C #), как я могу удалять файлы в определенном каталоге старше 3 месяцев, но я предполагаю, что период даты может быть гибким.

Для ясности: я ищу файлы старше 90 дней, другими словами, файлы, созданные менее 90 дней назад, должны быть сохранены, а все остальные удалены.

JL.
источник
Если имеется большое количество файлов, лучше всего использовать EnumerateFiles и EnumerateDirectories вместо GetFiles и GetDirectories, поскольку они напрямую запускают перечисление, а не собирают список. Однако вам придется использовать цикл foreach.
Ларри

Ответы:

258

Что-то вроде этого outta do it.

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();
}
Стив Даннер
источник
Спасибо, я заметил, что вы используете lastAccessTime, это время создания?
JL.
10
нет, как сказано в propertyNames: LastAccessTime- CreationTimeесли хотите, вам следует купить недвижимость !
Андреас Нидермайр
4
Да, вы сами решаете, какую собственность использовать. Вы также можете использовать LastWriteTime, если хотите.
Стив Даннер,
3
+1 за то, что помог мне. Вместо создания нового экземпляра FileInfo вы можете использовать File.GetCreationTime или File.GetLastAccessTime. Должно быть небольшое улучшение производительности.
Марио Ложка,
5
Полагаю, GetFiles и Delete никогда не подведут в вашей среде? Просто указываю на это, так как это, кажется, очень цитируемый ответ.
Эндрю Хагнер
93

Вот однострочная лямбда:

Directory.GetFiles(dirName)
         .Select(f => new FileInfo(f))
         .Where(f => f.LastAccessTime < DateTime.Now.AddMonths(-3))
         .ToList()
         .ForEach(f => f.Delete());
Ури Абрамсон
источник
@VladL Я получаю сообщение «IEnumerable <FileInfo> не содержит ForEach», если отбрасываю ToList (). Я просто сохранил это.
Джеймс Лав
3
Мне это нравится. Но я бы
обернул
new DirectoryInfo(dir).GetFiles()быстрее, чем new FileInfo(f)для каждого отдельного файла.
Vojtěch
29

Для тех, кто любит чрезмерно использовать 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 (). Где (x => x.LastAccessTime <DateTime.Now.AddMonths (-3)); // изменение
Ta01
2
Woho! Кто-то другой, кроме меня, считает, что чрезмерное использование LINQ - это здорово! ;)
Филип Экберг
Что .ToList()добавляет вызов, кроме второго цикла через совпадающие файлы?
Джоэл Мюллер
2
@ Джоэль Мюллер. List<T>определяет ForEachметод, который можно использовать для применения Action<T>ко всем элементам. К сожалению, такого метода расширения для IEnumerable<T>.
Сэмюэл Нефф
1
Хорошая точка зрения. Я написал свой собственный ForEachметод расширения IEnumerable<T>так давно, что иногда забываю, что он не встроен.
Джоэл Мюллер,
14

Вот фрагмент того, как узнать время создания файлов в каталоге и найти те, которые были созданы 3 месяца назад (точнее, 90 дней назад):

    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();
        }
    }
Пьер-Люк Шампиньи
источник
Нет необходимости ToList(), DirectoryInfo.GetFiles()возвращает FileInfo[].
Dynami Le Savard
4
Вы должны объявить новую переменную вне foreach()цикла, в которой будет храниться значение (DateTime.Now- new TimeSpan(90, 0, 0, 0)). Нет смысла вычислять это повторно в цикле.
Чад
1

В основном вы можете использовать Directory.Getfiles (Path), чтобы получить список всех файлов. После этого вы просматриваете список и вызываете GetLastAccessTim (), как предложил Кейт.

Ян Джейкобс
источник
1

Что-то такое

            foreach (FileInfo file in new DirectoryInfo("SomeFolder").GetFiles().Where(p => p.CreationTime < DateTime.Now.AddDays(-90)).ToArray())
                File.Delete(file.FullName);
Яннис Леусис
источник
1

Я попробовал этот код, и он работает очень хорошо, надеюсь, это ответил

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 дней <> 3 месяца
Дэниел
1

Самый канонический подход, когда вы хотите удалить файлы в течение определенного времени, - это использовать LastWriteTime файла (последний раз, когда файл был изменен):

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

(Вышеупомянутое основано на ответе Ури, но с LastWriteTime.)

Всякий раз, когда вы слышите, как люди говорят об удалении файлов старше определенного периода времени (что является довольно распространенным действием), почти всегда они ищут выполнение этого на основе LastModifiedTime файла.

В качестве альтернативы, в очень необычных обстоятельствах вы можете использовать нижеприведенное, но используйте их с осторожностью, поскольку они содержат оговорки.

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

Время создания файла в текущем месте. Однако будьте осторожны, если файл был скопирован, это будет время его копирования и CreationTimeбудет новее, чем файл LastWriteTime.

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

Если вы хотите удалить файлы в зависимости от того, когда они были прочитаны в последний раз, вы можете использовать это, но нет никакой гарантии, что он будет обновлен, так как его можно отключить в NTFS. Проверьте, fsutil behavior query DisableLastAccessгорит ли он. Также в NTFS для обновления LastAccessTime файла после обращения к нему может потребоваться до часа.

Толга
источник
0

вам просто нужен FileInfo -> CreationTime

а чем просто рассчитать разницу во времени.

в app.config вы можете сохранить значение TimeSpan того, сколько лет должно быть удалено файлу.

также проверьте метод DateTime Subtract .

удачи

nWorx
источник
0

В качестве альтернативы вы можете использовать метод File.GetCreationTime, если вам нужно удалить файлы на основе дат создания.

jinsungy
источник
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);
                }
            }

использование при загрузке страницы или веб-сервисе или любое другое использование.

Моя концепция - каждые 7 дней, мне нужно удалить файл папки без использования БД

Вишал
источник
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

Например: чтобы перейти к проекту «Моя папка» в источнике, мне нужно открыть две папки. Я делаю этот алгоритм на 2 дня в неделю и на 4 часа

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

Я использую следующее в консольном приложении, работающем как служба, для получения информации о каталоге из файла App.Settings. Количество дней для хранения файлов также можно настроить, умноженное на -1 для использования в методе AddDays () 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
источник
0

Пример типа SSIS .. (если это кому-то поможет)

          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

так как решения с new FileInfo(filePath)не легко проверяемыми, я предлагаю использовать Упаковщик для классов , как Directory, Fileи Pathкак это:

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

Затем используйте что-то вроде этого:

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
источник
0

Просто создайте небольшую функцию удаления, которая поможет вам в решении этой задачи. Я протестировал этот код, и он отлично работает.

Эта функция удаляет файлы старше 90 дней, а также файл с расширением .zip, который нужно удалить из папки.

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
Рахит Растоги
источник