How to order list of files by file name with number?

It sounds like you might be looking for a “NaturalSort” – the kind of display File Explorer uses to order filenames containing numerals. For this you need a custom comparer:

Imports System.Runtime.InteropServices

Partial Class NativeMethods
    <DllImport("shlwapi.dll", CharSet:=CharSet.Unicode)>
    Private Shared Function StrCmpLogicalW(s1 As String, s2 As String) As Int32
    End Function

    Friend Shared Function NaturalStringCompare(str1 As String, str2 As String) As Int32
        Return StrCmpLogicalW(str1, str2)
    End Function
End Class

Public Class NaturalStringComparer
    Implements IComparer(Of String)

    Public Function Compare(x As String, y As String) As Integer Implements IComparer(Of String).Compare
        Return NativeMethods.NaturalStringCompare(x, y)
    End Function
End Class

Use it to sort the results you get:

Dim myComparer As New NaturalStringComparer

' OP post only shows the filename without path, so strip off path:
' (wont affect the result, just the display)
Dim files = Directory.EnumerateFiles(path_name_here).
                 Select(Function(s) Path.GetFileName(s)).ToList
Console.WriteLine("Before: {0}", String.Join(", ", files))

' sort the list using the Natural Comparer:
files.Sort(myComparer)
Console.WriteLine("After: {0}", String.Join(", ", files))

Results (one-lined to save space):

Before: file-1.txt, file-10.txt, file-11.txt, file-19.txt, file-2.txt, file-20.txt, file-3.txt, file-9.txt, file-99.txt
After: file-1.txt, file-2.txt, file-3.txt, file-9.txt, file-10.txt, file-11.txt, file-19.txt, file-20.txt, file-99.txt

One of the advantages of this is that it doesnt rely on a specific pattern or coding. It is more all-purpose and will handle more than one set of numbers in the text:

Game of Thrones\4 – A Feast For Crows\1 – Prologue.mp3
Game of Thrones\4 – A Feast For Crows\2 – The Prophet.mp3

Game of Thrones\4 – A Feast For Crows\10 – Brienne II.mp3
Game of Thrones\4 – A Feast For Crows\11 – Sansa.mp3


A Natural String Sort is so handy, is is something I personally dont mind polluting Intellisense with by creating an extension:

' List<string> version
<Extension>
Function ToNaturalSort(l As List(Of String)) As List(Of String)
    l.Sort(New NaturalStringComparer())
    Return l
End Function

' array version
<Extension>
Function ToNaturalSort(a As String()) As String()
    Array.Sort(a, New NaturalStringComparer())
    Return a
End Function

Usage now is even easier:

Dim files = Directory.EnumerateFiles(your_path).
              Select(Function(s) Path.GetFileName(s)).
              ToList.
              ToNaturalSort()

' or without the path stripping:
Dim files = Directory.EnumerateFiles(your_path).ToList.ToNaturalSort()

Leave a Comment