All, I have written some code to get the latest files from a directory, the files I am looking for contain the string sProcScript = "sProcScript" and in the selected directory I might have several versions:


and I want to pick up the latest version only (the version number being the number after the file name i.e. 1007 etc.). So in the above this would be sProcScriptBigGuns1007.sql and sProcScriptEdAggVal1007.sql. To do this I wrote the following snippet (as part of a larger method), where strPath is the path to the relevant directory

DirectoryInfo dirInfo = new DirectoryInfo(strPath);
List<FileInfo> listFileInfo = new List<FileInfo>();
listFileInfo = dirInfo.EnumerateFiles().ToList<FileInfo>();

// Loop in to locate special processes.
List<FileInfo> specialProcList = new List<FileInfo>();
foreach (FileInfo fi in listFileInfo)
    if (Path.GetFileNameWithoutExtension(fi.FullName).Contains(sProcScript))

// Get distinct.
List<string> nameList = new List<string>();
foreach (FileInfo fi in specialProcList)
    string strsProc = 
        Path.GetFileNameWithoutExtension(Regex.Replace(fi.Name, @"[\d]", String.Empty));
    if (!nameList.Contains(strsProc))
List<FileInfo> tmpList;
List<string> tmpNameList = new List<string>();
tmpList = specialProcList.OrderByDescending(f => f.Name).ToList();
foreach (string name in nameList)
    foreach (FileInfo fi in tmpList)
        if (fi.Name.Contains(name))

which works great. However, I think there will be a much better and neater way of doing this using LINQ but I am new to LINQ and can't seem to get started with it (the attempts I have made are poor enough to not want to post them here!). Can someone demonstate a better way of doing the above operation using LINQ?

Thanks for your time.

  • \$\begingroup\$ This is not a code review question. I have demonstrated a viable solution to illustrate I don't want the work done for me. The question could be answered without the code snippet. \$\endgroup\$
    – Killercam
    Jul 10, 2012 at 14:12
  • \$\begingroup\$ This is part of even larger method? I think writing smaller methods would make your code more readable. \$\endgroup\$
    – svick
    Jul 10, 2012 at 15:04

4 Answers 4


Another one (assuming the filename is always SomeCharactersSomeNumbers.extension):

void Main()
    var sProcScript = "sProcScript";

    var fileNames = new [] {"sProcScriptBigGuns1001.sql", 

    var grouped = from f in fileNames
                  where f.Contains(sProcScript)
                  let m = new {FileName = f, 
                               Group = new string(f.TakeWhile(c=>!Char.IsDigit(c)).ToArray()),
                               Version = Int32.Parse(new string(f.Where(c=>Char.IsDigit(c)).ToArray()))}
                  group m by m.Group;

    var files = grouped.Select(g => g.OrderByDescending(f => f.Version).First().FileName);                    

    foreach (var file in files)


This should do it:

var selectedFileInfos = listFileInfo
    .Where(x => { 
        var filename = Path.GetFileNameWithoutExtension(x.FullName); 
        return specialProcList.Any(y => filename.Contains(y);})
    .OrderByDescending(x => x.Name)
    .GroupBy(x => Path.GetFileNameWithoutExtension(Regex.Replace(x.Name, @"[\d]", String.Empty)) 
    .Select(x => x.First());

But be careful: file numbers should be padded with zeros. 0001, 0900, 0999, 1000, 1001. If they are just normally numbered with 1, 900, 999, 1000 etc., even your code will fail.

  • \$\begingroup\$ Thanks very much, however the edit to you answer was required to get it to work. The edit compiles but returns nothing - can you advise. Again, thanks very much for your time... \$\endgroup\$
    – MoonKnight
    Jul 10, 2012 at 14:30


    .Select(f => new { FileName = f, SprocName = regex.Replace(Path.GetFileNameWithoutExtension(f), ""), Version = int.Parse(regex.Match(f).Value) })
    .Where(f => f.FileName.Contains(sProcScript))
    .GroupBy(f => f.SprocName)
    .Select(g => new { Sproc = g.Key, MaxVersion = g.Max(s => s.Version) })

How about:

var files = from file in new DirectoryInfo(strPath).EnumerateFiles()
            let nameWithoutEx = Path.GetFileNameWithoutExtension(file.Name)
            where nameWithoutEx.Contains(sProcScript)
            let key = new string(nameWithoutEx.Reverse()
            group file by key into versionGroup
            select versionGroup
                  .OrderBy(f => int.Parse(new string(f.Name
  • \$\begingroup\$ Thanks but as this stands it won't compile due to a number of errors. Thanks for your time... \$\endgroup\$
    – MoonKnight
    Jul 10, 2012 at 14:43
  • \$\begingroup\$ @Killercam: Didn't try, but what are the errors? What version of C# / .NET are you on? \$\endgroup\$
    – Ani
    Jul 10, 2012 at 14:45
  • \$\begingroup\$ Framework 4.0, there were a few. I have an answer above working so I wont waste anymore of your time. But thanks you very much for your response it is most appreciated. \$\endgroup\$
    – MoonKnight
    Jul 10, 2012 at 14:50
  • \$\begingroup\$ @Killercam: The only thing missing was the ToArray() calls. Fine now. \$\endgroup\$
    – Ani
    Jul 10, 2012 at 14:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.