2009-07-24 7 views
97

Necesito encontrar el archivo modificado más recientemente en un directorio.¿Cómo encontrar el archivo más reciente en un directorio usando .NET y sin bucles?

Sé que puedo recorrer todos los archivos en una carpeta y comparar File.GetLastWriteTime, pero ¿hay una mejor manera de hacerlo sin bucle ?.

+15

No hay nada mejor que evita bucle. Incluso el uso de LINQ oculta el bucle en una funcionalidad más profunda donde no se puede ver directamente. – Oliver

+1

Si quiere encontrar los archivos modificados más recientemente en todo el sistema de archivos, entonces el NTFS Change Journal sería útil. Sin embargo, es muy difícil de usar desde C#. –

Respuesta

220

¿qué tal algo como esto ...

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, encuentro que la versión no azucarada es más fácil de leer: 'directory.GetFiles(). OrderByDescending (f => f.LastWriteTime) .First()' –

+5

Sí, estoy de acuerdo la mayor parte del tiempo también, pero cuando dando ejemplos, la sintaxis de la consulta hace que sea un poco más obvio que es una consulta de linq. Actualizaré el ejemplo con ambas opciones para aclarar. –

+3

¡Gracias! Ahora solo necesito convencer a mi jefe de que agilice el proceso de actualizarnos de .net 2.0 para que pueda usar Linq :) –

1

Puede reaccionar a la actividad de archivos nuevos con FileSystemWatcher.

+1

No funciona porque un archivo se puede modificar mientras su aplicación no se está ejecutando. –

+1

no dio ese tipo de detalles ... ¿Cómo sabemos que no es una aplicación persistente? –

+1

No, pero Scott tiene una mejor solución que funciona en ambos casos. – Badaro

9

Una versión no 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

Lo siento, no he visto el hecho de que no deseabas repetir. De todos modos ... quizás ayude a alguien que busque algo similar – TimothyP

+3

Este código no se compila. - lastUpdatedFile no debe ser una matriz. - El valor inicial de lastUpdate no es válido (0001/0/0). –

18

Si desea buscar de forma recursiva, puede utilizar esta hermosa pieza de código:

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

a llamarlo de la siguiente manera:

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

y eso es todo. Devuelve una instancia de FileInfo o null si el directorio está vacío.

+8

O puede usar la opción [búsqueda recursiva] (http://msdn.microsoft.com/en-us/library/ms143327 (v = vs.110) .aspx). – ricksmt

+2

Buen código. es realmente útil – 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

Alguna explicación hubiera sido agradable, aquí –

+1

Creo que el código es bastante claro y no necesita explicaciones. – vikasde

14

Ampliando el primero anterior, si desea buscar un cierto patrón que puede utilizar el siguiente código:

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

Aquí hay una versión que obtiene el archivo más reciente de cada subdirectorio

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

que es un poco tarde, pero ...

su código no funcionará, b a causa de list<FileInfo> lastUpdateFile = null; y más tarde lastUpdatedFile.Add(file); por lo que se lanzará la excepción de NullReference. versión de trabajo debe ser:

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

Gracias

0

hago esto es un montón de mis aplicaciones y utilizar una sentencia como esta:

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

Desde aquí tendrá el nombre de archivo el archivo guardado/agregado/actualizado más recientemente en el Directorio de la variable "inputDirectory". Ahora puedes acceder a él y hacer lo que quieras con él.

Espero que ayude.

1

corto y simple:

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