C# Sort files by natural number ordering in the name?

I know this might be late, but here is another solution which works perfectly

FileInfo[] files = di.GetFiles().OrderBy(n => Regex.Replace(n.Name, @"\d+", n => n.Value.PadLeft(4, '0')));

Using Regex replace in the OrderBy Clause:

Regex.Replace(n.Name, @"\d+", n => n.Value.PadLeft(4, '0'))

So what this does, it pads the numeric values in the file name with a length of 4 chars in each number:

0-0.jpeg     ->   0000-0000.jpeg
0-1.jpeg     ->   0000-0001.jpeg
0-5.jpeg     ->   0000-0005.jpeg
0-9.jpeg     ->   0000-0009.jpeg
0-10.jpeg    ->   0000-0010.jpeg
0-12.jpeg    ->   0000-0012.jpeg

But this only happens in the OrderBy clause, it does not touch the original file name in any way. The order you will end up with in the array is the "human natural" order.


Alphabetically, the "wrong" order is in fact correct. If you want it sorted numerically then you'll need to either:

  1. convert the filenames to a list of numeric numbers and sort them
  2. name the files in such a way that alphabetic and numeric sorting are the same (0-001.jpeg and 0-030.jpg)
  3. rely on the file creation time to sort (presuming the files were created in order).

See the answer to Sorting Directory.GetFiles() for an example of #3.


See the "CustomSort" function here.

List<string> list = new List<string>() { 
                    "0-5.jpeg",
                    "0-9.jpeg",
                    "0-0.jpeg",
                    "0-1.jpeg",
                    "0-10.jpeg",
                    "0-12.jpeg"};
list.CustomSort().ToList().ForEach(x => Console.WriteLine(x));

Its output:

0-0.jpeg
0-1.jpeg
0-5.jpeg
0-9.jpeg
0-10.jpeg
0-12.jpeg

Tags:

C#