Видаліть файли, старші 3 місяців, у каталог за допомогою .NET


117

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

Просто для того, щоб було зрозуміло: я шукаю файли, старші 90 днів, іншими словами файли, створені менше 90 днів тому, слід зберігати, а всі інші видаляти.


Якщо є важлива кількість файлів, найкраще використовувати EnumerateFiles та EnumerateDirectories замість GetFiles та GetDirectories, оскільки вони безпосередньо виконують перерахування замість того, щоб збирати список. Однак вам доведеться використовувати петлю foreach.
Ларрі

Відповіді:


257

Щось подібне це робить.

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

Ось 1-лайнер лямбда:

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 = новий DirectoryInfo (@ "C: \ Temp"). GetFiles (). Де (x => x.LastAccessTime <DateTime.Now.AddMonths (-3)); // варіація
Ta01

2
Вухо! Хтось інший, ніж я, вважає, що надмірне використання 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()повертає a FileInfo[].
Динамі" Ле Савард

4
Вам слід оголосити нову змінну поза foreach()циклом, щоб утримувати значення (DateTime.Now- new TimeSpan(90, 0, 0, 0)). Немає підстав обчислювати це повторно в циклі.
Чад


1

В основному ви можете використовувати Directory.Getfiles (Шлях), щоб отримати список усіх файлів. Після цього ви перебираєте список і викликаєте 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 .

Щасти



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

використання для завантаження сторінки, веб-сервісу чи будь-якого іншого використання.

Моя концепція - це evrry 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 дні на тиждень і на чотири години

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

        }

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

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.