Como encontrar o arquivo mais recente em um diretório usando .NET e sem loop?
142
Preciso encontrar o arquivo modificado mais recentemente em um diretório.
Eu sei que posso percorrer todos os arquivos em uma pasta e comparar File.GetLastWriteTime, mas existe uma maneira melhor de fazer isso sem fazer um loop?
Não, não existe melhor maneira de evitar o loop. Mesmo o uso do LINQ oculta o loop em algumas funcionalidades mais profundas, nas quais você não pode vê-lo diretamente.
Oliver
1
Se você deseja encontrar os arquivos modificados mais recentemente em todo o sistema de arquivos, o Diário de alterações do NTFS será útil. Muito, muito difícil de usar a partir de C #.
Ben Voigt 27/05
Respostas:
318
Que tal algo como isso...
var directory =newDirectoryInfo("C:\\MyDirectory");var myFile =(from f in directory.GetFiles()orderby f.LastWriteTimedescendingselect f).First();// or...var myFile = directory.GetFiles().OrderByDescending(f => f.LastWriteTime).First();
Pessoalmente, acho que a versão não-açucarada é mais fácil de ler:directory.GetFiles().OrderByDescending(f => f.LastWriteTime).First()
Jørn Schou-Rode
6
Sim, eu concordo na maioria das vezes também - mas, ao dar exemplos, a sintaxe da consulta torna um pouco mais óbvio que é uma consulta linq. Vou atualizar o exemplo com as duas opções para esclarecer.
23911 Scott Ivey
3
Obrigado! Agora eu só preciso convencer meu chefe para agilizar o processo de modernização us a partir .NET 2.0 para que eu possa usar Linq :)
Chris Klepeis
3
você pode usar LINQ com 2.0 SP1 com um pouco de trabalho extra - basta fazer referência ao arquivo System.Core.dll de 3,5, e configurá-lo para "copiar local"
Scott Ivey
8
Isso não deveria ser usado em FirstOrDefault()vez de First()? Este último causará um InvalidOperationExceptionse o diretório estiver vazio.
Tobias J
20
Se você deseja pesquisar recursivamente, pode usar este belo pedaço de código:
/// <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>privatestaticDateTimeGetLatestWriteTimeFromFileInDirectory(DirectoryInfo directoryInfo){if(directoryInfo ==null||!directoryInfo.Exists)returnDateTime.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>privatestaticFileInfoGetLatestWritenFileFileInDirectory(DirectoryInfo directoryInfo){if(directoryInfo ==null||!directoryInfo.Exists)returnnull;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;}
seu código não funcionará, por causa list<FileInfo> lastUpdateFile = null;
e mais tarde, lastUpdatedFile.Add(file);então a exceção NullReference será lançada. A versão de trabalho deve ser:
Faço isso em vários aplicativos e uso uma declaração como esta:
var inputDirectory =newDirectoryInfo("\\Directory_Path_here");var myFile = inputDirectory.GetFiles().OrderByDescending(f => f.LastWriteTime).First();
A partir daqui, você terá o nome do arquivo para o arquivo salvo / adicionado / atualizado mais recentemente no diretório da variável "inputDirectory". Agora você pode acessá-lo e fazer o que quiser com ele.
Para adicionar isso, se seu objetivo é recuperar o caminho do arquivo e você estiver usando FirstOrDefault porque é possível que não haja resultados, você pode usar o operador condicional nulo na propriedade FullName. Isso retornará "nulo" para o seu caminho sem precisar salvar o FileInfo do FirstOrDefault antes de chamar FullName. caminho da cadeia de caracteres = new DirectoryInfo (caminho). GetFiles (). OrderByDescending (o => o.LastWriteTime) .FirstOrDefault () ?. FullName;
Respostas:
Que tal algo como isso...
fonte
directory.GetFiles().OrderByDescending(f => f.LastWriteTime).First()
FirstOrDefault()
vez deFirst()
? Este último causará umInvalidOperationException
se o diretório estiver vazio.Se você deseja pesquisar recursivamente, pode usar este belo pedaço de código:
Basta chamá-lo da seguinte maneira:
e é isso. Retorna uma
FileInfo
instância ounull
se o diretório está vazio.fonte
Expandindo o primeiro acima, se você deseja procurar um determinado padrão, pode usar o seguinte código:
fonte
Uma versão não-LINQ:
fonte
Curto e simples :
fonte
é um pouco tarde, mas ...
seu código não funcionará, por causa
list<FileInfo> lastUpdateFile = null;
e mais tarde,lastUpdatedFile.Add(file);
então a exceção NullReference será lançada. A versão de trabalho deve ser:obrigado
fonte
Você pode reagir à nova atividade de arquivo com o FileSystemWatcher .
fonte
Outra abordagem, se você estiver usando
Directory.EnumerateFiles
e quiser ler os arquivos modificados pela última vez primeiro.fonte
Aqui está uma versão que obtém o arquivo mais recente de cada subdiretório
fonte
fonte
Faço isso em vários aplicativos e uso uma declaração como esta:
A partir daqui, você terá o nome do arquivo para o arquivo salvo / adicionado / atualizado mais recentemente no diretório da variável "inputDirectory". Agora você pode acessá-lo e fazer o que quiser com ele.
Espero que ajude.
fonte