Click here to Skip to main content
15,880,972 members
Please Sign up or sign in to vote.
3.00/5 (1 vote)
Dear all,

first of all let me try to describe what i am trying to do.

lets say we have several files in a Folder. The Names are name as follows:

Report 1 2017-08-01.xls
Report 1 2017-08-09.xls
Report 1 2017-08-27.xls
Report 1 2017-09-01.xls
Report 1 2017-09-09.xls
Report 1 2017-09-18.xls

Report 2 2017-08-01.xls
Report 2 2017-08-09.xls
Report 2 2017-08-27.xls
Report 2 2017-09-01.xls
Report 2 2017-09-09.xls
Report 2 2017-09-22.xls

Report 3 2017-08-01 blabla.xls
Report 3 2017-08-09 blabla.xls
Report 3 2017-08-27 blabla.xls
Report 3 2017-09-01 blabla.xls
Report 3 2017-09-09 blabla.xls
Report 3 2017-09-30 blabla.xls

Now.

I want to delete all Files expect the Latest File Of each report of each month.

So the result would be. Delete all Files expext the Files:

Report 1 2017.08.27.xls
Report 1 2017-09-18.xls

Report 2 2017-08-27.xls
Report 2 2017-09-22.xls

Report 3 2017-08-27 blabla.xls
Report 3 2017-09-30 blabla.xls

So first i Listed all files and the belonging Folder in a Gridview.

Then i extracted all Dates with Regex. So far so good.

My Problem is how to delete only the latest of each Filename for each month. does anyone have an suggestion?

Here is my code.

      private void button1_Click(object sender, EventArgs e)
      {
          string fileName= "";



          string[] folders  = Directory.GetDirectories(@"C:\Test\", "*", System.IO.SearchOption.AllDirectories);



              for (int i = 0; i < folders.Length; i++)
              {
                  string temp = "";
                  Console.WriteLine("Pfad " + i + " " + folders.GetValue(i));
                  temp = folders.GetValue(i).ToString();

                  dataGridView1.Rows[i].Cells[0].Value = temp;


if ((Directory.GetFiles(temp, "*", SearchOption.TopDirectoryOnly).Length) == 0)

                  {

                 dataGridView1.Rows[i].Cells[1].Value = "No Files in Path";
                  }

                  else

                  {
                      for (int k = 0; k < (Directory.GetFiles(temp, "*", SearchOption.TopDirectoryOnly).Length); k++)
                      {
                          string tempfile = "";
                          tempfile = (Directory.GetFiles(temp, "*", SearchOption.TopDirectoryOnly).GetValue(k).ToString());
                      fileName = Path.GetFileName(tempfile).ToString();

                    Console.WriteLine(Regex.Match(fileName, @"\d{4}-\d{2}-\d{2}"));


                      dataGridView1.Rows[i + k].Cells[0].Value = temp;
                      dataGridView1.Rows[i + k].Cells[1].Value = Path.GetFileName(tempfile).ToString();
                      dataGridView1.Rows[i+k].Cells[2].Value = Regex.Match(fileName, @"\d{4}-\d{2}-\d{2}"));



                  }
                  }


              }
          }



Your help would be highly appriciated.

Thank you very much.

What I have tried:

To list all Files and the dates but dont know how to delete only the latest.
Posted
Updated 9-Nov-17 0:35am
v4
Comments
Graeme_Grant 9-Nov-17 6:06am    
Putting all of your question in Bold Text is considered SHOUTING! Please don't. Click on the Improve question widget to fix. Thank you.
Member 12341536 9-Nov-17 6:07am    
im sorry i did it accidently
Graeme_Grant 9-Nov-17 6:32am    
All good. Enjoy the solution... :)

This will do it succinctly for you:
C#
var inFiles = new List<string>
{
    "Report 1 2017-08-01.xls",
    "Report 1 2017-08-09.xls",
    "Report 1 2017-08-27.xls",
    "Report 1 2017-09-01.xls",
    "Report 1 2017-09-09.xls",
    "Report 1 2017-09-18.xls",
    "Report 2 2017-08-01.xls",
    "Report 2 2017-08-09.xls",
    "Report 2 2017-08-27.xls",
    "Report 2 2017-09-01.xls",
    "Report 2 2017-09-09.xls",
    "Report 2 2017-09-22.xls",
    "Report 3 2017-08-01 blabla.xls",
    "Report 3 2017-08-09 blabla.xls",
    "Report 3 2017-08-27 blabla.xls",
    "Report 3 2017-09-01 blabla.xls",
    "Report 3 2017-09-09 blabla.xls",
    "Report 3 2017-09-30 blabla.xls"
};

var deleteFiles = inFiles.Select(x => new { date = DateTime.Parse(Regex.Match(x, @"\d{4}-\d{2}-\d{2}").Value), file = x })
                            .Select(x => new { id = x.file.Replace(x.date.ToString("yyyy-MM-dd"), ""), date = x.date, file = x.file })
                            .OrderByDescending(x => x.date)
                            .GroupBy(x => x.id)
                            .SelectMany(x => x.Skip(1).Select(y => y.file));

foreach (var file in deleteFiles)
{
    Console.WriteLine(file);
}

Outputs:
Report 3 2017-09-09 blabla.xls
Report 3 2017-09-01 blabla.xls
Report 3 2017-08-27 blabla.xls
Report 3 2017-08-09 blabla.xls
Report 3 2017-08-01 blabla.xls
Report 2 2017-09-09.xls
Report 2 2017-09-01.xls
Report 2 2017-08-27.xls
Report 2 2017-08-09.xls
Report 2 2017-08-01.xls
Report 1 2017-09-09.xls
Report 1 2017-09-01.xls
Report 1 2017-08-27.xls
Report 1 2017-08-09.xls
Report 1 2017-08-01.xls


UPDATE
To keep the most recent of each month, we need to expand the grouping to also include year and month. This will create more groups which is what we want:
C#
var deleteFiles =
    inFiles.Select(x => new
                    {
                        date = DateTime.Parse(Regex.Match(x, @"\d{4}-\d{2}-\d{2}").Value),
                        file = x
                    })
            .Select(x => new
                    {
                        id = x.file.Replace(x.date.ToString("yyyy-MM-dd"), ""),
                        year = x.date.Year,
                        month = x.date.Month,
                        date = x.date,
                        file = x.file
                    })
            .OrderByDescending(x => x.date)
            .GroupBy(x => new { id = x.id, year = x.year, month = x.month })
            .SelectMany(x => x.Skip(1).Select(y => y.file));

Now the output is:
Report 3 2017-09-09 blabla.xls
Report 3 2017-09-01 blabla.xls
Report 2 2017-09-09.xls
Report 2 2017-09-01.xls
Report 1 2017-09-09.xls
Report 1 2017-09-01.xls
Report 1 2017-08-09.xls
Report 1 2017-08-01.xls
Report 2 2017-08-09.xls
Report 2 2017-08-01.xls
Report 3 2017-08-09 blabla.xls
Report 3 2017-08-01 blabla.xls

Here is a bonus piece of code for you... It will tell you which files are being kept:
C#
Console.WriteLine("-- Keeping:");
foreach (var file in inFiles.Except(deleteFiles))
{
    Console.WriteLine(file);
}

Which outputs:
-- Keeping:
Report 1 2017-08-27.xls
Report 1 2017-09-18.xls
Report 2 2017-08-27.xls
Report 2 2017-09-22.xls
Report 3 2017-08-27 blabla.xls
Report 3 2017-09-30 blabla.xls
 
Share this answer
 
v3
Comments
Member 12341536 9-Nov-17 6:47am    
Hi greame_Grant thank you very much for your answer.
I am not sure if this is all what i need. Your output gives me the Files which should be deleted right? But these contains the files which should not be deleted too. It only leaves me the latest Files from the latest month. But as is mentioned i need it for each month.

The Files

Report 1 2017-08-27.xls
Report 2 2017-08-27.xls
Report 3 2017-08-27 blabla.xls

should not be deleted too.

Really appreciate your help.
Graeme_Grant 9-Nov-17 6:49am    
The framework is there, you just need to change the grouping to id, then year, then month.

Solution is updated... ;)
Member 12341536 9-Nov-17 8:44am    
Thanks a lot, really appreciate your help. Thanks
Graeme_Grant 9-Nov-17 9:08am    
You are most welcome. I hope, with the way that the code is laid out, that it makes it easy to see what it is doing... ;)
Ralf Meier 9-Nov-17 8:48am    
+5
How would you do it if you do it by yourself ?
I would build a List only with those files which have the same Reportname, Year and Month.
Now sort this List descending - after that you will get the latest File on Top. Each FileName at the List-Entry 1 or higher could be deleted.
Repeat this with the next Month and after that the next Year and then the next Reportname ...
If your Reportnames are unique you can do all this with Loops ...
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900