0

I have a folder that has a number of subfolders that are named as such (2 digit month + 4 digit year) as an example.

102018, 062014, 092018, 042016, 072017, 012016

I need to get a folder list to be able to loop through that is sorted by the year part of the name and then the month part of the name. The name format is always a 2 digit month and a 4 digit year.

The list should then be sorted like

102018, 092018, 072017, 042016, 012016, 062014

I can use the code to get a list

string[] SubDirs = Directory.GetDirectories(@"c:\MainFolder\");

but I don't know how to sort the folder names as I need. Can anyone help?

4 Answers 4

1

You can temporarily store the date as yyyyMM and sort on that.

To avoid problems extracting the date, I made sure that the directory name starts with six digits.

using System;
using System.Linq;
using System.IO;
using System.Text.RegularExpressions;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            string dirToExamine = @"C:\temp\testDirs";

            /* Get the directories which start with six digits */
            var re = new Regex("^[0-9]{6}");
            var dirs = new DirectoryInfo(dirToExamine).GetDirectories()
                .Where(d => re.IsMatch(d.Name))
                .ToList();

            /* The directory names start MMyyyy but we want them ordered by yyyyMM */
            var withDates = dirs.Select(d => new
            {
                Name = d,
                YearMonth = d.Name.Substring(2, 4) + d.Name.Substring(0, 2)
            })
                .OrderByDescending(f => f.YearMonth, StringComparer.OrdinalIgnoreCase)
                .Select(g => g.Name).ToList();

            Console.WriteLine(string.Join("\r\n", withDates));
            Console.ReadLine();

        }
    }
}

(It may look like a lot of code, but I formatted it to fit the width of this column.)

I tested it on these directory names (listed with dir /b):

012016abcd
042016
062014
0720179876
092018
102018 Some text

and got the required ordering:

102018 Some text
092018
0720179876
042016
012016abcd
062014

If you then wanted to do something with the files in each of those directories in that order, it is quite easy because you can use .GetFiles() on a DirectoryInfo instance:

foreach(var di in withDates)
{
    FileInfo[] files = di.GetFiles();
    foreach(var fil in files)
    {
        Console.WriteLine(fil.Name);
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

How would I get the resultant list of folders into a string array?
@Andy Instead of the .ToList() at the end, put .ToArray().
Sorry for the brutally dumb comment but what would be the name of the array? withDates?
@Andy No problem, yes that is correct, but you can change it to whatever makes sense for your program.
Thank you so much for your help Andrew! One last thing. The results in the array seem to be of type DirectoryInfo. I was expecting just a string with the 2 digit month and 4 digit year. My next step is to list all the files in each folder (as you've now so cleverly sorted!) as I loop through the array. I'm not sure how to do this with this type. I know I'm asking over and above.
1

Try this

string[] foldernames = Directory.GetDirectories(@"c:\MainFolder\");
List<DateTime> result =  new List<DateTime>();
foreach (var element in foldernames)
{
    result.Add(DateTime.Parse(element.Substring(0,2)+"-"+element.Substring(2)));
}


result.OrderByDescending(d => d).Select(s => new {SortedFile = s.ToShortDateString().Replace(@"/1/","")});

Or

result.OrderByDescending(d => d).Select(s => 
      s.ToShortDateString().Replace(@"/1/",""));

result will contain names in the order you need

Comments

1

For the specified format of folder names you could use regular expressions, OrderByDescending and ThenByDescending methods. For example:

var year = new Regex(@"\d{4}$", RegexOptions.Compiled);
var month = new Regex(@"^\d{2}", RegexOptions.Compiled);
string[] SubDirs = Directory
    .GetDirectories(@"c:\MainFolder\")
    .OrderByDescending(dir => year.Match(dir)?.Value, StringComparer.OrdinalIgnoreCase)
    .ThenByDescending(dir => month.Match(dir)?.Value, StringComparer.OrdinalIgnoreCase)
    .ToArray();

Comments

0

You can use Array.Sort, using the second parameter to provide a delegate function, that will slice the string to its 3 parts (year, month day) and return the proper order.

1 Comment

I've looked up sorting with a delegate and I think I'm more confused now on how to do it. Could you give me a simple code example? The name contains only a 2 digit month and then a 4 digit year. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.