0

I have 1000 files in a folder, I want to find the name of the file, but when I do it The file names are not sorted.

For example: These are my filenames

1-CustomerApp.txt
2-CustomerApp.txt
3-CustomerApp.txt
...

screenshot

var adddress = @"data\"; 
str = "";
DirectoryInfo d = new DirectoryInfo(adddress);//Assuming Test is your Folder
FileInfo[] Files = d.GetFiles("*.txt"); //Getting Text files
foreach (FileInfo file in Files)
{
    str = str + ", " + file.Name;
}
CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
object json
  • 615
  • 1
  • 8
  • 20
  • 5
    They ARE sorted, but sorted as strings. When you have 1 2 10, they will be sorted as 1 10 2. – Tony Dec 18 '13 at 08:16
  • 2
    @Tony: if they *happen* to be sorted it's only because of a filesystem quirk (usually NTFS). The same code run against the same set of files on an NFS or FAT partition will yield vastly different results. – Sam Axe Dec 18 '13 at 08:18
  • Related question: [Natural Sort Order in C#](https://stackoverflow.com/questions/248603/natural-sort-order-in-c-sharp) – CodesInChaos Dec 18 '13 at 08:22
  • Take a look at: [this answer][1]... [1]: http://stackoverflow.com/questions/12077182/c-sharp-sort-files-by-natural-number-ordering-in-the-name – user844541 Dec 18 '13 at 08:23
  • What is your question? How is finding a file related to sorting file names? – JeffRSon Dec 18 '13 at 08:24
  • @Dan-o The point is that he wrote they are unsorted, but they ARE. – Tony Dec 18 '13 at 08:24
  • @Tony: No. The point is that any observed similarity to any kind of sortedness [numerical or alphabetical] is purely happenstance, a coincidence, a side effect. *The observation is incorrect!* – Sam Axe Dec 18 '13 at 08:28

4 Answers4

8

You could use this to keep a "numerical" order

FileInfo[] files = d.GetFiles("*.txt")
.OrderBy(m => m.Name.PadLeft(200, '0')).ToArray();

200 is quite arbitrary, of course.

This will add "as many 0 as needed" so that the file name + n 0 are a string with a length of 200.

to make it a little bit less arbitrary and "brittle", you could do

var f = d.GetFiles("*.txt");
var maxLength = f.Select(l => l.Name.Length).Max() + 1;
FileInfo[] files = f.OrderBy(m => m.Name.PadLeft(maxLength, '0')).ToArray();

How does it work (bad explanation, someone could do better) and why is it far from perfect :

Ordering of characters in c# puts numeric characters before alpha characters. So 0 (or 9) will be before a. But 10a, will be before 2a as 1 comes before 2.

see char after char

1 / 2 => 10a first

But if we change 10a and 2a, with PadLeft, to 010a and 002a, we see, character after character

0 / 0 => equal

1 / 0 => 002a first

This "works" in your case, but really depends on your "file naming" logic.

CAUTION : This solution won't work with other file naming logic

For example, the numeric part is not at the start.

f-2-a and f-10-a

Because

00-f-2-a would still be before 0-f-10-a

or the "non-numeric part" is not of the same length.

1-abc and 2-z

Because 01-abc will come after 0002-z

Raphaël Althaus
  • 59,727
  • 6
  • 96
  • 122
0

They are sorted alphabetically. I don't know how do you see what they are not sorted (with what you compare or where have you seen different result), if you are using file manager, then perhaps it apply own sorting. In windows explorer result will be the same (try to sort by name column).

If you know template of how file name is created, then you can do a trick, to apply own sorting. In case of your example, extract number at start (until minus) and pad it with zeroes (until maximum possible number size), and then sort what you get.

Or you can pad with zeroes when files are created:

0001-CustomerApp.txt
0002-CustomerApp.txt
...
9999-CustomerApp.txt
Sinatr
  • 20,892
  • 15
  • 90
  • 319
0

Try the alphanumeric-sorting and sort the files' names according to it.

FileInfo[] files = d.GetFiles("*.txt");
files.OrderBy(file=>file.Name, new AlphanumComparatorFast())
user844541
  • 2,868
  • 5
  • 32
  • 60
0

This should give you more or less what you want; it skips any characters until it hits a number, then includes all directly following numerical characters to get the number. That number is then used as a key for sorting. Somewhat messy perhaps, but should work (and be less brittle than some other options, since this searches explicitly for the first "whole" number within the filename):

var filename1 = "10-file.txt";
var filename2 = "2-file.txt";

var filenames = new []{filename1, filename2};

var sorted = 
    filenames.Select(fn => new { 
                                  nr = int.Parse(new string(
                                             fn.SkipWhile(c => !Char.IsNumber(c))
                                               .TakeWhile(c => Char.IsNumber(c))
                                               .ToArray())), 
                                  name = fn
                                })
              .OrderBy(file => file.nr)
              .Select(file => file.name);
Kjartan
  • 18,591
  • 15
  • 71
  • 96