Joel Coehoorn
Joel Coehoorn

Reputation: 415600

Sorting Directory.GetFiles()

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.

Upvotes: 69

Views: 166127

Answers (13)

skeltech
skeltech

Reputation: 31

A more succinct VB.Net version...is very nice. Thank you. To traverse the list in reverse order, add the reverse method...

For Each fi As IO.FileInfo In filePaths.reverse
  ' Do whatever you wish here
Next

Upvotes: 3

Kibbee
Kibbee

Reputation: 66112

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

Upvotes: 9

Simon Molloy
Simon Molloy

Reputation: 1864

A more succinct VB.Net version, if anyone is interested

Dim filePaths As Linq.IOrderedEnumerable(Of IO.FileInfo) = _
  New DirectoryInfo("c:\temp").GetFiles() _
   .OrderBy(Function(f As FileInfo) f.CreationTime)
For Each fi As IO.FileInfo In filePaths
  ' Do whatever you wish here
Next

Upvotes: 1

sebastiaan
sebastiaan

Reputation: 5917

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)

Upvotes: 12

Ian Nelson
Ian Nelson

Reputation: 58703

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.

Upvotes: 114

Mehdi Anis
Mehdi Anis

Reputation: 358

Just an idea. I like to find an easy way out and try re use already available resources. if I were to sort files I would've just create a process and make syscal to "DIR [x:\Folders\SubFolders*.*] /s /b /on" and capture the output.

With system's DIR command you can sort by :

/O          List by files in sorted order.
sortorder    N  By name (alphabetic)       S  By size (smallest first)
             E  By extension (alphabetic)  D  By date/time (oldest first)
             G  Group directories first    -  Prefix to reverse order

The /S switch includes sub folders

I AM NOT SURE IF D = By Date/Time is using LastModifiedDate or FileCreateDate. But if the needed sort order is already built-in in the DIR command, I will get that by calling syscall. And it's FAST. I am just the lazy guy ;)

After a little googling I found switch to sort by particular date/time:-

/t [[:]TimeField] : Specifies which time field to display or use for sorting. The following list describes each of the values you can use for TimeField. 

Value Description 
c : Creation
a : Last access
w : Last written

Upvotes: 1

Chris Karcher
Chris Karcher

Reputation: 2292

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);
                                    });

Upvotes: 13

Vertigo
Vertigo

Reputation: 2746

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

Upvotes: 3

samjudson
samjudson

Reputation: 56853

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.

Upvotes: 2

Tina Marie
Tina Marie

Reputation: 83

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).

Upvotes: 2

GateKiller
GateKiller

Reputation: 75869

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.

Upvotes: 3

Vaibhav
Vaibhav

Reputation: 11436

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

Upvotes: 2

Guy Starbuck
Guy Starbuck

Reputation: 21873

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.

Upvotes: 6

Related Questions