2009-07-24 15 views
97

Ho bisogno di trovare il file modificato più di recente in una directory.Come trovare il file più recente in una directory utilizzando .NET e senza eseguire il ciclo?

So che posso scorrere tutti i file in una cartella e confrontare File.GetLastWriteTime, ma c'è un modo migliore per farlo senza eseguire il ciclo ?.

+15

No non c'è modo migliore che evita loop. Anche l'utilizzo di LINQ nasconde semplicemente il loop in alcune funzionalità più profonde in cui non è possibile vederlo direttamente. – Oliver

+1

Se si desidera trovare il file oi file modificati più di recente sull'intero filesystem, il journal delle modifiche NTFS sarebbe utile. Molto molto difficile da usare da C#, però. –

risposta

220

come su qualcosa di simile ...

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(); 
+66

Personalmente, trovo che la versione non zuccherata sia più facile da leggere: 'directory.GetFiles(). OrderByDescending (f => f.LastWriteTime) .First()' –

+5

sì, sono d'accordo anche la maggior parte del tempo - ma quando dando esempi la sintassi della query rende un po 'più ovvio che si tratta di una query linq. Aggiornerò l'esempio con entrambe le opzioni per chiarire. –

+3

Grazie! Ora ho solo bisogno di convincere il mio capo ad accelerare il processo di aggiornamento da .net 2.0 in modo da poter usare Linq :) –

1

È possibile rispondere alla nuova attività file con FileSystemWatcher.

+1

Non funziona perché un file può essere modificato mentre la sua applicazione non è in esecuzione. –

+1

non ha dato quel tipo di dettaglio ... Come facciamo a sapere che non è un'app persistente? –

+1

Noi no, ma Scott ha una soluzione migliore che funziona in entrambi i casi. – Badaro

9

Una versione non 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

Siamo spiacenti, non ho visto il fatto che non volevi eseguire il ciclo. Comunque ... forse aiuterà qualcuno a cercare qualcosa di simile – TimothyP

+3

Questo codice non viene compilato. - lastUpdatedFile non dovrebbe essere una matrice. - Il valore iniziale per lastUpdate non è valido (0001/0/0). –

18

Se si desidera effettuare la ricerca in modo ricorsivo, è possibile utilizzare questo bel pezzo di codice:

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

Basta chiamarlo nel seguente modo:

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

e il gioco è fatto. Restituisce un'istanza FileInfo o null se la directory è vuota.

+8

Oppure è possibile utilizzare l'opzione [ricerca ricorsiva] (http://msdn.microsoft.com/en-us/library/ms143327 (v = vs.110) .aspx). – ricksmt

+2

Bel codice. è veramente d'aiuto – Monika

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

Qualche spiegazione sarebbe stata buona, qui –

+1

Penso che il codice sia abbastanza chiaro e non abbia bisogno di spiegazioni. – vikasde

14

espansione sulla prima sopra, se si desidera cercare un determinato modello è possibile utilizzare il seguente codice:

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

Ecco una versione che ottiene il file più recente da ogni sottodirectory

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)); 
2

è un po 'in ritardo ma ...

il codice non funziona, b a causa di list<FileInfo> lastUpdateFile = null; e successivo a lastUpdatedFile.Add(file); quindi verrà generata l'eccezione NullReference. versione di lavoro dovrebbe essere:

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

Grazie

0

faccio questo è un mucchio delle mie applicazioni e utilizzare un'istruzione come questa:

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

Da qui si avrà il nome del file per il file salvato/aggiunto/aggiornato più recente nella directory della variabile "inputDirectory". Ora puoi accedervi e fare ciò che vuoi con esso.

Spero che questo aiuti.

1

breve e semplice:

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