.NET kullanarak ve döngü olmadan en son dosya nasıl bulunur?


142

Bir dizinde en son değiştirilen dosyayı bulmam gerekiyor.

Bir klasördeki her dosya üzerinden döngü ve karşılaştırma biliyorum File.GetLastWriteTime, ama döngü olmadan bunu yapmak için daha iyi bir yolu var mı ?.


18
Hayır, döngüden kaçınmanın daha iyi bir yolu yoktur. LINQ kullanmak bile, döngüyü doğrudan göremediğiniz daha derin bir işlevselliğe gizler.
Oliver

1
Tüm dosya sisteminde en son değiştirilen dosyaları bulmak istiyorsanız, NTFS Değişiklik Günlüğü yararlı olacaktır. Yine de C # kullanmak çok çok zor.
Ben Voigt

Yanıtlar:


318

böyle bir şeye ne dersin ...

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
Şahsen, şekersiz versiyonun okunmasının daha kolay olduğunu düşünüyorum:directory.GetFiles().OrderByDescending(f => f.LastWriteTime).First()
Jørn Schou-Rode

6
evet, ben de çoğu zaman katılıyorum - ama örnekler verirken sorgu sözdizimi biraz daha açık bir linq sorgusu yapar. Örneği açıklığa kavuşturmak için her iki seçenekle de güncelleyeceğim.
Scott Ivey

3
Teşekkürler! Şimdi patronumu Lin.'i kullanabilmemiz için bizi .net 2.0'dan yükseltme sürecini hızlandırmaya ikna etmem gerekiyor
Chris Klepeis

3
linq'i 2.0 SP1 ile biraz ekstra çalışma ile kullanabilirsiniz - 3.5'ten System.Core.dll dosyasına bakın ve "yerel kopyala" olarak ayarlayın
Scott Ivey

8
Bunun FirstOrDefault()yerine kullanmamalı First()mı? İkincisi InvalidOperationException, dizin boşsa bir neden olur .
Tobias J

20

Yinelemeli olarak arama yapmak istiyorsanız, bu güzel kod parçasını kullanabilirsiniz:

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

Sadece şu şekilde arayın:

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

ve bu kadar. Bir FileInfoörnek döndürür veya nulldizin boşsa.


12
Veya özyinelemeli arama seçeneğini kullanabilirsiniz.
ricksmt

17

Yukarıdaki ilkine genişleyerek, belirli bir deseni aramak istiyorsanız aşağıdaki kodu kullanabilirsiniz:

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

Buna ihtiyacım vardı. Teşekkür ederim.
ashilon

10

LINQ olmayan bir sürüm:

/// <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
Özür dileriz, döngü istemediğiniz gerçeğini görmedim. Her neyse ... belki de benzer bir şeyi arayan birine yardımcı olacaktır
TimothyP

3
Bu kod derlenmez. - lastUpdatedFile bir dizi olmamalıdır. - lastUpdate için başlangıç ​​değeri geçersiz (0001/0/0).
Lars A. Brekken

4

Kısa ve basit :

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

3

biraz geç ama ...

kodunuz çalışmaz, çünkü list<FileInfo> lastUpdateFile = null; daha sonra lastUpdatedFile.Add(file);NullReference istisnası atılır. Çalışma sürümü şöyle olmalıdır:

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

Teşekkürler


2

FileSystemWatcher ile yeni dosya etkinliğine tepki verebilirsiniz .


1
Bir dosya, uygulaması çalışmazken değiştirilebilir.
Francis B.24

1
böyle bir ayrıntı vermedi ... Bunun kalıcı bir uygulama olmadığını nereden biliyoruz?
Scott Marlowe

1
Yapmıyoruz, ama Scott her iki durumda da işe yarayan daha iyi bir çözüme sahip.
Badaro

Ayrıca, FSW'nin ağ paylaşımlı klasörlerin çoğunda çalışmayacağını unutmayın.
bkqc

2

Başka bir yaklaşım kullanıyorsanız Directory.EnumerateFilesve ilk önce değiştirilen dosyaları okumak istiyorsanız.

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

}

1

Her alt dizinden en son dosyayı alan bir sürüm

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

Bu benim uygulamalar bir grup yapmak ve böyle bir ifade kullanın:

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

Buradan, "inputDirectory" değişkeninin Dizininde en son kaydedilen / eklenen / güncellenen dosya için dosya adına sahip olacaksınız. Artık ona erişebilir ve istediğinizi yapabilirsiniz.

Umarım yardımcı olur.


Buna eklemek için, hedefiniz dosya yolunu geri almaksa ve sonuç olmadığından dolayı FirstOrDefault kullanıyorsanız, FullName özelliğinde null koşullu işleci kullanabilirsiniz. Bu, FullName çağırmadan önce FirstOrDefault gelen FileInfo kaydetmek zorunda kalmadan yolunuz için "null" geri döndürür. string path = yeni DirectoryInfo (yol) .GetFiles (). OrderByDescending (o => o.LastWriteTime) .FirstOrDefault () ?. FullName;
StalePhish
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.