Sorting Directory.GetFiles()

Viewed 157564

System.IO.Directory.GetFiles() returns a string[]. What is the default sort order for the returned values? I'm assuming by name, but if so how much does the current culture effect it? Can you change it to something like creation date?

Update: MSDN points out that the sort order is not guaranteed for .Net 3.5, but the 2.0 version of the page doesn't say anything at all and neither page will help you sort by things like creation or modification time. That information is lost once you have the array (it contains only strings). I could build a comparer that would check for each file it gets, but that means accessing the file system repeatedly when presumably the .GetFiles() method already does this. Seems very inefficient.

13 Answers

If you're interested in properties of the files such as CreationTime, then it would make more sense to use System.IO.DirectoryInfo.GetFileSystemInfos(). You can then sort these using one of the extension methods in System.Linq, e.g.:

DirectoryInfo di = new DirectoryInfo("C:\\");
FileSystemInfo[] files = di.GetFileSystemInfos();
var orderedFiles = files.OrderBy(f => f.CreationTime);

Edit - sorry, I didn't notice the .NET2.0 tag so ignore the LINQ sorting. The suggestion to use System.IO.DirectoryInfo.GetFileSystemInfos() still holds though.

In .NET 2.0, you'll need to use Array.Sort to sort the FileSystemInfos.

Additionally, you can use a Comparer delegate to avoid having to declare a class just for the comparison:

DirectoryInfo dir = new DirectoryInfo(path);
FileSystemInfo[] files = dir.GetFileSystemInfos();

// sort them by creation time
Array.Sort<FileSystemInfo>(files, delegate(FileSystemInfo a, FileSystemInfo b)
                                    {
                                        return a.LastWriteTime.CompareTo(b.LastWriteTime);
                                    });

Here's the VB.Net solution that I've used.

First make a class to compare dates:

Private Class DateComparer
    Implements System.Collections.IComparer

    Public Function Compare(ByVal info1 As Object, ByVal info2 As Object) As Integer Implements System.Collections.IComparer.Compare
        Dim FileInfo1 As System.IO.FileInfo = DirectCast(info1, System.IO.FileInfo)
        Dim FileInfo2 As System.IO.FileInfo = DirectCast(info2, System.IO.FileInfo)

        Dim Date1 As DateTime = FileInfo1.CreationTime
        Dim Date2 As DateTime = FileInfo2.CreationTime

        If Date1 > Date2 Then Return 1
        If Date1 < Date2 Then Return -1
        Return 0
    End Function
End Class

Then use the comparer while sorting the array:

Dim DirectoryInfo As New System.IO.DirectoryInfo("C:\")
Dim Files() As System.IO.FileInfo = DirectoryInfo.GetFiles()
Dim comparer As IComparer = New DateComparer()
Array.Sort(Files, comparer)

Dim Files() As String
Files = System.IO.Directory.GetFiles("C:\")
Array.Sort(Files)

From msdn:

The order of the returned file names is not guaranteed; use the Sort() method if a specific sort order is required.

The Sort() method is the standard Array.Sort(), which takes in IComparables (among other overloads), so if you sort by creation date, it will handle localization based on the machine settings.

You are correct, the default is my name asc. The only way I have found to change the sort order it to create a datatable from the FileInfo collection.

You can then used the DefaultView from the datatable and sort the directory with the .Sort method.

This is quite involve and fairly slow but I'm hoping someone will post a better solution.

You can implement custom iComparer to do sorting. Read the file info for files and compare as you like.

IComparer comparer = new YourCustomComparer();
Array.Sort(System.IO.Directory.GetFiles(), comparer);

msdn info IComparer interface

The MSDN Documentation states that there is no guarantee of any order on the return values. You have to use the Sort() method.

You could write a custom IComparer interface to sort by creation date, and then pass it to Array.Sort. You probably also want to look at StrCmpLogical, which is what is used to do the sorting Explorer uses (sorting numbers correctly with text).

If you want to sort by something like creation date you probably need to use DirectoryInfo.GetFiles and then sort the resulting array using a suitable Predicate.

Related