.NETを使用して、ループせずにディレクトリで最新のファイルを見つける方法は?


142

最近変更されたファイルをディレクトリで見つける必要があります。

フォルダー内のすべてのファイルをループして比較できることはわかっていますが、File.GetLastWriteTimeループせずにこれを行うより良い方法はありますか?


18
ループを回避するより良い方法はありません。LINQを使用しても、直接表示されない一部のより深い機能へのループを隠すだけです。
オリバー

1
ファイルシステム全体で最近変更されたファイルを見つけたい場合は、NTFS変更ジャーナルが役立ちます。ただし、C#からの使用は非常に困難です。
Ben Voigt 2014年

回答:


318

このようなものはどうですか...

var directory = new DirectoryInfo("C:\\MyDirectory");
var myFile = (from f in directory.GetFiles()
             orderby f.LastWriteTime descending
             select f).First();

// or...
var myFile = directory.GetFiles()
             .OrderByDescending(f => f.LastWriteTime)
             .First();

84
個人的には、砂糖をdirectory.GetFiles().OrderByDescending(f => f.LastWriteTime).First()
使わ

6
ええ、私もほとんどの場合同意しますが、例を示すと、クエリ構文により、それがlinqクエリであることが少し明確になります。わかりやすくするために、両方のオプションを使用して例を更新します。
スコットアイビー

3
ありがとう!今、私は上司に.net 2.0からのアップグレードプロセスを促進するように説得する必要があるだけなので、Linqを使用できます:)
Chris Klepeis 2009

3
2.0 SP1でlinqを少し追加の作業で使用できます-3.5からSystem.Core.dllファイルを参照し、それを「ローカルにコピー」に設定します
Scott Ivey

8
FirstOrDefault()代わりにこれを使用するべきではありませんFirst()か?後者はInvalidOperationException、ディレクトリが空の場合にを引き起こします。
トビアスJ

20

再帰的に検索したい場合は、次の美しいコードを使用できます。

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

次のように呼び出すだけです。

FileInfo newestFile = GetNewestFile(new DirectoryInfo(@"C:\directory\"));

以上です。FileInfoインスタンスを返すnullか、ディレクトリが空の場合。


12
または、再帰検索オプションを使用できます。
ricksmt 2014年

17

上記の最初のパターンを展開して、特定のパターンを検索する場合は、次のコードを使用できます。

string pattern = "*.txt";
var dirInfo = new DirectoryInfo(directory);
var file = (from f in dirInfo.GetFiles(pattern) orderby f.LastWriteTime descending select f).First();

私はそれが必要でした。ありがとうございました。
アシロン

10

非LINQバージョン:

/// <summary>
/// Returns latest writen file from the specified directory.
/// If the directory does not exist or doesn't contain any file, DateTime.MinValue is returned.
/// </summary>
/// <param name="directoryInfo">Path of the directory that needs to be scanned</param>
/// <returns></returns>
private static DateTime GetLatestWriteTimeFromFileInDirectory(DirectoryInfo directoryInfo)
{
    if (directoryInfo == null || !directoryInfo.Exists)
        return DateTime.MinValue;

    FileInfo[] files = directoryInfo.GetFiles();
    DateTime lastWrite = DateTime.MinValue;

    foreach (FileInfo file in files)
    {
        if (file.LastWriteTime > lastWrite)
        {
            lastWrite = file.LastWriteTime;
        }
    }

    return lastWrite;
}

/// <summary>
/// Returns file's latest writen timestamp from the specified directory.
/// If the directory does not exist or doesn't contain any file, null is returned.
/// </summary>
/// <param name="directoryInfo">Path of the directory that needs to be scanned</param>
/// <returns></returns>
private static FileInfo GetLatestWritenFileFileInDirectory(DirectoryInfo directoryInfo)
{
    if (directoryInfo == null || !directoryInfo.Exists)
        return null;

    FileInfo[] files = directoryInfo.GetFiles();
    DateTime lastWrite = DateTime.MinValue;
    FileInfo lastWritenFile = null;

    foreach (FileInfo file in files)
    {
        if (file.LastWriteTime > lastWrite)
        {
            lastWrite = file.LastWriteTime;
            lastWritenFile = file;
        }
    }
    return lastWritenFile;
}

1
申し訳ありませんが、ループしたくないという事実は表示されませんでした。とにかく...おそらくそれは、誰かが似たような検索をするのに役立ちます
TimothyP

3
このコードはコンパイルされません。-lastUpdatedFileは配列であってはなりません。-lastUpdateの初期値が無効です(0001/0/0)。
Lars A. Brekken

4

短くてシンプル

new DirectoryInfo(path).GetFiles().OrderByDescending(o => o.LastWriteTime).FirstOrDefault();

3

少し遅いけど...

list<FileInfo> lastUpdateFile = null; 後でコードが機能しないため、lastUpdatedFile.Add(file);NullReference例外がスローされます。作業バージョンは次のとおりです。

private List<FileInfo> GetLastUpdatedFileInDirectory(DirectoryInfo directoryInfo)
{
    FileInfo[] files = directoryInfo.GetFiles();
    List<FileInfo> lastUpdatedFile = new List<FileInfo>();
    DateTime lastUpdate = DateTime.MinValue;
    foreach (FileInfo file in files)
    {
        if (file.LastAccessTime > lastUpdate)
        {
            lastUpdatedFile.Add(file);
            lastUpdate = file.LastAccessTime;
        }
    }

    return lastUpdatedFile;
}

ありがとう


2

FileSystemWatcherを使用して、新しいファイルのアクティビティに対応できます


1
アプリケーションが実行されていないときにファイルを変更できるため、機能しません。
フランシスB.

1
彼はそのような詳細を与えませんでした...それが永続的なアプリではないことをどうやって知るのですか?
スコットマーロウ

1
私たちはそうではありませんが、スコットは両方のケースで機能するより良い解決策を持っています。
Badaro、

また、FSWはほとんどのネットワーク共有フォルダーでは機能しないことに注意してください。
bkqc

2

あなたが使用Directory.EnumerateFilesしていて、最初に変更された最新のファイルを読みたい場合の別のアプローチ。

foreach (string file in Directory.EnumerateFiles(fileDirectory, fileType).OrderByDescending(f => new FileInfo(f).LastWriteTime))

}

1

これは、各サブディレクトリから最新のファイルを取得するバージョンです

List<string> reports = new List<string>();    
DirectoryInfo directory = new DirectoryInfo(ReportsRoot);
directory.GetFiles("*.xlsx", SearchOption.AllDirectories).GroupBy(fl => fl.DirectoryName)
.ForEach(g => reports.Add(g.OrderByDescending(fi => fi.LastWriteTime).First().FullName));

0
private List<FileInfo> GetLastUpdatedFileInDirectory(DirectoryInfo directoryInfo)
{
    FileInfo[] files = directoryInfo.GetFiles();
    List<FileInfo> lastUpdatedFile = null;
    DateTime lastUpdate = new DateTime(1, 0, 0);
    foreach (FileInfo file in files)
    {
        if (file.LastAccessTime > lastUpdate)
        {
            lastUpdatedFile.Add(file);
            lastUpdate = file.LastAccessTime;
        }
    }

    return lastUpdatedFile;
}

0

これは私のアプリの束であり、次のようなステートメントを使用します。

  var inputDirectory = new DirectoryInfo("\\Directory_Path_here");
  var myFile = inputDirectory.GetFiles().OrderByDescending(f => f.LastWriteTime).First();

ここから、「inputDirectory」変数のディレクトリに、最後に保存/追加/更新されたファイルのファイル名が表示されます。今、あなたはそれにアクセスして、あなたが望むことをそれで行うことができます。

お役に立てば幸いです。


これに追加するには、ファイルパスを取得することが目的であり、結果がない可能性があるためFirstOrDefaultを使用している場合は、FullNameプロパティでnull条件演算子を使用できます。これにより、FullNameを呼び出す前にFirstOrDefaultからFileInfoを保存せずに、パスに対して「null」が返されます。文字列path = new DirectoryInfo(path).GetFiles()。OrderByDescending(o => o.LastWriteTime).FirstOrDefault()?. FullName;
StalePhish
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.