4

Ans: Here is one solution for getting latest file name from folder using c# code

Call Function as follows:

FileInfo newestFile = GetNewestFile(new DirectoryInfo(@"D:\DatabaseFiles"));

Function:

public static FileInfo GetNewestFile(DirectoryInfo directory)
        {
            return directory.GetFiles()
                .Union(directory.GetDirectories().Select(d => GetNewestFile(d)))
                .OrderByDescending(f => (f == null ? DateTime.MinValue : f.LastWriteTime))
                .FirstOrDefault();
        }

Now my question is someone please tell me alternative way to get newest file name from folder?

Samad
  • 71
  • 2
  • 10
  • Why need something else? What are your criteria for "better"? – DrKoch Jan 23 '15 at 10:46
  • As an aside, why do you check for `null`? [`DirectoryInfo.GetFiles`](https://msdn.microsoft.com/en-us/library/ms143327%28v=vs.110%29.aspx) never returns files which are `null`. – Tim Schmelter Jan 23 '15 at 10:54
  • LastWriteTime in the solutions below will be wrong if one of the other files is modified. LastWrite means just that. The last time the file was written to. If you want a more sure way to get the last file, keep a history of the existing files and compare them with new snapshots for everytime you check. Go for the LastWriteTime on the new files. You could use the CreationTime instead, but note that if the file is overwritten the old date might still be on the new file. I suggest a combination of CreationTime and LastWriteTime. – Wolf5 Jan 23 '15 at 11:40

2 Answers2

4

Doing an entire sort just to find the largest item in a list is extremely inefficient.

You would be better using one of the "MaxBy()" Linq extensions to find the maximum value, such as the MoreLinq one from Jon Skeet and others. (The full library is here.)

If you use MaxBy() the code might look something like this:

public static FileInfo GetNewestFile(DirectoryInfo directory)
{
    return directory.GetFiles()
        .Union(directory.GetDirectories().Select(d => GetNewestFile(d)))
        .MaxBy(f => (f == null ? DateTime.MinValue : f.LastWriteTime));
}

Ideally you would combine this with the other suggested answer (i.e. use the overload of Directory.EnumerateFiles() which does the recursion for you).

Here's a complete console app sample. The "MaxBy()" method was sourced and somewhat modified from an old version of MoreLinq:

using System;
using System.Collections.Generic;
using System.IO;

namespace Demo
{
    public static class Program
    {
        private static void Main()
        {
            string root = "D:\\Test"; // Put your test root here.

            var di = new DirectoryInfo(root);
            var newest = GetNewestFile(di);

            Console.WriteLine("Newest file = {0}, last written on {1}", newest.FullName, newest.LastWriteTime);
        }

        public static FileInfo GetNewestFile(DirectoryInfo directory)
        {
            return directory.EnumerateFiles("*.*", SearchOption.AllDirectories)
                .MaxBy(f => (f == null ? DateTime.MinValue : f.LastWriteTime));
        }
    }

    public static class EnumerableMaxMinExt
    {
        public static TSource MaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
        {
            return source.MaxBy(selector, Comparer<TKey>.Default);
        }

        public static TSource MaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector, IComparer<TKey> comparer)
        {
            using (IEnumerator<TSource> sourceIterator = source.GetEnumerator())
            {
                if (!sourceIterator.MoveNext())
                {
                    throw new InvalidOperationException("Sequence was empty");
                }

                TSource max = sourceIterator.Current;
                TKey maxKey = selector(max);

                while (sourceIterator.MoveNext())
                {
                    TSource candidate = sourceIterator.Current;
                    TKey candidateProjected = selector(candidate);

                    if (comparer.Compare(candidateProjected, maxKey) > 0)
                    {
                        max = candidate;
                        maxKey = candidateProjected;
                    }
                }

                return max;
            }
        }
    }
}
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
1

You could use the override that does the recursion for you (The rest of the code is from your question)

return directory.GetFiles("*", SearchOption.AllDirectories)
                .OrderByDescending(f => (f == null ? DateTime.MinValue : f.LastWriteTime))
                .FirstOrDefault(); 

There is also the EnumerateFiles which may be better (deferred execution)

return directory.EnumerateFiles("*", SearchOption.AllDirectories)
                .OrderByDescending(f => (f == null ? DateTime.MinValue : f.LastWriteTime))
                .FirstOrDefault(); 
Sayse
  • 42,633
  • 14
  • 77
  • 146