.NET을 사용하고 루핑하지 않고 디렉토리에서 최신 파일을 찾는 방법은 무엇입니까?


142

디렉토리에서 가장 최근에 수정 된 파일을 찾아야합니다.

폴더의 모든 파일을 반복하고 비교할 수 있다는 것을 알고 File.GetLastWriteTime있지만 반복하지 않고이를 수행하는 더 좋은 방법이 있습니까?


18
루핑을 피하는 더 좋은 방법은 없습니다. LINQ를 사용하더라도 직접 볼 수없는 더 깊은 기능으로 루핑을 숨길 수 있습니다.
Oliver

1
전체 파일 시스템에서 가장 최근에 수정 된 파일을 찾으려면 NTFS 변경 저널이 유용합니다. 그러나 C #에서는 사용하기가 매우 어렵습니다.
Ben Voigt

답변:


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()
Jørn Schou-Rode

6
예, 대부분의 경우에도 동의합니다. 그러나 예제를 제공 할 때 쿼리 구문을 사용하면 linq 쿼리라는 것이 좀 더 분명해집니다. 명확히하기 위해 두 가지 옵션으로 예제를 업데이트하겠습니다.
Scott Ivey

3
감사! 이제 Linq를 사용할 수 있도록 상사에게 .net 2.0에서 업그레이드하는 과정을 신속히 처리하도록 설득해야합니다. :)
Chris Klepeis

3
약간의 추가 작업으로 linq를 2.0 SP1과 함께 사용할 수 있습니다. 3.5의 System.Core.dll 파일을 참조하여 "로컬 복사"로 설정하십시오
Scott Ivey

8
FirstOrDefault()대신에 이것을 사용해서는 안 First()됩니까? 후자는 InvalidOperationException디렉토리가 비어 있으면 발생합니다 .
Tobias 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

17

위의 첫 번째 패턴을 확장하여 특정 패턴을 검색하려면 다음 코드를 사용할 수 있습니다.

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

나는 그것을 필요로했다. 감사합니다.
ashilon

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
그의 응용 프로그램이 실행되지 않는 동안 파일을 수정할 수 있기 때문에 작동하지 않습니다.
Francis B.

1
그는 그런 종류의 세부 사항을주지 않았다 ... 우리는 그것이 지속적인 앱이 아니라는 것을 어떻게 알 수 있는가?
Scott Marlowe

1
우리는 그렇지 않지만 Scott은 두 경우 모두 작동하는 더 나은 솔루션을 가지고 있습니다.
Badaro

또한 FSW는 대부분의 네트워크 공유 폴더에서 작동하지 않습니다.
bkqc 2016 년

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를 저장하지 않고 경로에 대해 "널"을 반환합니다. 문자열 경로 = 새 DirectoryInfo (경로) .GetFiles (). OrderByDescending (o => o.LastWriteTime) .FirstOrDefault () ?. FullName;
StalePhish 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.