Koby Douek
Koby Douek

Reputation: 16675

Get directory files, ordered by a date which is part of the file name

I need to get all the files from a directory, ordered by the date which is present as part of the files name:

James_2015.06.27.pdf
Anna_2017.01.17.pdf
Timmy_2017.02.19.pdf

Currently, I'm using this, which only sorts the files by Name.

 DirectoryInfo info = new DirectoryInfo(path);
 FileInfo[] files = info.GetFiles(filter).OrderBy(p => p.Name).ToArray();

Any ideas how can I achieve this?

Upvotes: 0

Views: 371

Answers (3)

Jeroen van Langen
Jeroen van Langen

Reputation: 22038

You need to parse the filename:

DirectoryInfo info = new DirectoryInfo(path);
FileInfo[] files = info.GetFiles(filter)
    .OrderBy(p => Path.GetFileNameWithoutExtension(p.FullName).Split('_')[1])
    .ToArray();

But this is error prone.


Using linq

Like I said, this is error prone, I would probably write something like this:

DirectoryInfo info = new DirectoryInfo(path);


FileInfo[] files = (from fileInfo in info.GetFiles(filter)
                    let splitted = Path.GetFileNameWithoutExtension(fileInfo.FullName).Split('_')
                    where splitted.Length > 1
                    orderby splitted[1]
                    select fileInfo).ToArray();

A better way would be parsing the datetime and sort on it.

This will also filter on the files that doesn't have a valid date within the filename.

private DateTime? ParseFilename(FileInfo fileInfo)
{
    var parts = Path.GetFileNameWithoutExtension(fileInfo.FullName).Split('_');
    if (parts.Length < 1)
        return null;

    DateTime result;

    if (!DateTime.TryParse(parts[1], out result))
        return null;

    return result;
}

Usage:

DirectoryInfo info = new DirectoryInfo(path);

FileInfo[] files = (from fileInfo in info.GetFiles(filter)
                    let DateTime = ParseFilename(fileInfo)
                    where DateTime.HasValue
                    orderby DateTime.Value
                    select fileInfo).ToArray();

Upvotes: 4

kurdy
kurdy

Reputation: 471

I would create a dictionary with the Filename as Key and the value would be a substring from the filename and only contain the date.

You can loop over your DirectoryEntrys and add them to the dictionary in a loop, the algorithm would be like that:

                        string filename1 = "asbdahszd2018.02.01.pdf";
                        string filename2 = "foobar2018.02.01.pdf";

                        Dictionary<string, string> myDict = new Dictionary<string,string>();

                        myDict.Add(filename1, filename1.Substring(filename1.Length - 14, 10));
                        myDict.Add(filename2, filename2.Substring(filename2.Length - 14, 10));

                        myDict.OrderBy(item => item.Value);

Upvotes: 0

Uladzimir Palekh
Uladzimir Palekh

Reputation: 1871

This should work for you:

DirectoryInfo info = new DirectoryInfo(path);
FileInfo[] files = info.GetFiles(filter).OrderBy(p => Path.GetFileNameWithoutExtension(p.Name).Split('_').Last()).ToArray();

Upvotes: 1

Related Questions