여러 파일 확장자 searchPattern for System.IO.Directory.GetFiles


140

여러 파일 확장자를 다음 과 같이 설정하는 구문은 무엇입니까searchPattern 에가 Directory.GetFiles()? 예를 들어 확장자 가 .aspx.ascx 인 파일을 필터링합니다 .

// TODO: Set the string 'searchPattern' to only get files with
// the extension '.aspx' and '.ascx'.
var filteredFiles = Directory.GetFiles(path, searchPattern);

최신 정보 : LINQ는 옵션이 아니며 질문에 지정된대로 searchPattern전달 되어야합니다 GetFiles.


나는 아무것도 없다고 생각합니다. 모든 파일을 나열한 다음 수동으로 필터링하거나 여러 검색기에서 통합을 수행하십시오. 그러나 나는 전에 이렇게 정확한 질문을 보았을 것이라고 확신합니다.
코드 InChaos


이전에 질문하고 대답했습니다 : stackoverflow.com/questions/163162/…
David

답변:


41

"즉시 사용 가능한"솔루션이 없다고 생각합니다. 이는 Directory.GetFiles 메서드의 제한 사항입니다.

그래도 자신의 방법을 작성하는 것은 매우 쉽습니다 . 여기에 예가 있습니다.

코드는 다음과 같습니다.

/// <summary>
/// Returns file names from given folder that comply to given filters
/// </summary>
/// <param name="SourceFolder">Folder with files to retrieve</param>
/// <param name="Filter">Multiple file filters separated by | character</param>
/// <param name="searchOption">File.IO.SearchOption, 
/// could be AllDirectories or TopDirectoryOnly</param>
/// <returns>Array of FileInfo objects that presents collection of file names that 
/// meet given filter</returns>
public string[] getFiles(string SourceFolder, string Filter, 
 System.IO.SearchOption searchOption)
{
 // ArrayList will hold all file names
ArrayList alFiles = new ArrayList();

 // Create an array of filter string
 string[] MultipleFilters = Filter.Split('|');

 // for each filter find mathing file names
 foreach (string FileFilter in MultipleFilters)
 {
  // add found file names to array list
  alFiles.AddRange(Directory.GetFiles(SourceFolder, FileFilter, searchOption));
 }

 // returns string array of relevant file names
 return (string[])alFiles.ToArray(typeof(string));
}

7
각 필터에 대해 전체 디렉토리를 반복하므로이 방법은 매우 불충분 한 방법입니다. 대신 필터가 있는지 각 파일을 확인한 다음 목록을 추가하기 위해 추가해야합니다. 이 글에서 설명한 답변을 사용할 수 있습니다 : stackoverflow.com/questions/3754118/…
ot0

191
var filteredFiles = Directory
    .GetFiles(path, "*.*")
    .Where(file => file.ToLower().EndsWith("aspx") || file.ToLower().EndsWith("ascx"))
    .ToList();

2014-07-23 편집

빠른 열거를 위해 .NET 4.5에서이 작업을 수행 할 수 있습니다.

var filteredFiles = Directory
    .EnumerateFiles(path) //<--- .NET 4.5
    .Where(file => file.ToLower().EndsWith("aspx") || file.ToLower().EndsWith("ascx"))
    .ToList();

MSDN의 Directory.EnumerateFiles


5
@Mario Vernari :를 GetFiles반환합니다 string[].
jgauffin

4
EndsWith () 인수에서 *를 제거해야합니다. 와일드 카드 일치는 수행하지 않습니다.
Hans Passant

3
파일의 확장자를 비교하면 '.Where (file => new FileInfo (file) .Extension.Equals ( ". aspx") || new FileInfo (file) .Extension.Equals ( ". ascx")와 정확히 일치하는 값을 반환합니다. ) '
Damith

3
Directory.EnumerateFiles성능 향상을위한 새로운 .NET4 를 잊지 마십시오 ... stackoverflow.com/questions/5669617/…
drzaus

6
그리고 당신은 항상 사용할 수있는 file.EndsWith("...", StringComparison.InvariantCultureIgnoreCase);것이 아니라ToLower
drzaus

30

GetFiles는 단일 패턴과 만 일치 할 수 있지만 Linq를 사용하여 여러 패턴으로 GetFiles를 호출 할 수 있습니다.

FileInfo[] fi = new string[]{"*.txt","*.doc"}
    .SelectMany(i => di.GetFiles(i, SearchOption.AllDirectories))
    .ToArray();

여기에 의견 섹션을 참조하십시오 : http://www.codeproject.com/KB/aspnet/NET_DirectoryInfo.aspx


2
패턴이 겹치면 충돌합니다. 예, new string[]{"*.txt","filename.*"}. 그러나 DistinctFileInfo 객체는 시맨틱 등식이 아닌 참조 등식을 사용하여 비교하므로 실제로 호출하면 이 문제가 해결되지 않습니다. 를 제거 Distinct하거나에 전달 하여 해결할 수 있습니다 IEqualityComparer<FileInfo>. 전자를 편집했습니다.
Brian

난 그 생각 SelectMany이 성능면에서 차선이 될 수 있도록 다시 (다시) 같은 파일 구조를 반복합니다.
Dejan

28

읽을 수 있고 디렉토리의 여러 반복을 피하기 때문에이 방법을 좋아합니다.

var allowedExtensions = new [] {".doc", ".docx", ".pdf", ".ppt", ".pptx", ".xls", ".xslx"}; 
var files = Directory
    .GetFiles(folder)
    .Where(file => allowedExtensions.Any(file.ToLower().EndsWith))
    .ToList();

2
내 확장 배열을 구문 분석하고 정규식이나 다른 수동 작업에 추가 할 필요가 없기 때문에 이것을 훨씬 더 좋아합니다. 감사!
Ian Newland

@Jodrell, 또는 단순히HashSet<string>
Jodrell

확장의 수는 제한되고 EndsWith ()가 true가 될 때까지 배열은 각 파일에 대해 반복되므로 확장에 대한 배열 대신 HashSet <string>은 의미가 없습니다. 매우 많은 수의 확장에 대한 성능을 위해 메소드를 조정해야하는 경우 해시 세트를 사용할 수 있습니다. 적용하려면 각 파일의 확장명을 EndsWith () 메서드 대신 명시 적으로 일치시켜야합니다 (분할 후 일치). 이것은 가독성에 해를 끼치며 모든 실제 사용 사례는 아니지만 대부분의 경우 큰 의미가 없습니다. 커뮤니티 편집을 롤백했습니다.
Marc

15

나는 당신이 이와 같은 일을해야 할 것을 두려워합니다 . 여기 에서 정규 표현식을 변경 했습니다 .

var searchPattern = new Regex(
    @"$(?<=\.(aspx|ascx))", 
    RegexOptions.IgnoreCase);
var files = Directory.EnumerateFiles(path)
    .Where(f => searchPattern.IsMatch(f))
    .ToList();

이것은 좋은 접근 방법으로 보입니다. 빠진 부분은 테스트 된 (작동중인) 정규 표현식을 사용하는 것입니다.
Junior Mayhé

14
var filteredFiles = Directory
    .EnumerateFiles(path, "*.*") // .NET4 better than `GetFiles`
    .Where(
        // ignorecase faster than tolower...
        file => file.ToLower().EndsWith("aspx")
        || file.EndsWith("ascx", StringComparison.OrdinalIgnoreCase))
    .ToList();

또는 글로브를 분할하고 병합하는 것이 더 빠를 수 있습니다 (적어도 깔끔해 보입니다).

"*.ext1;*.ext2".Split(';')
    .SelectMany(g => Directory.EnumerateFiles(path, g))
    .ToList();

- 더 많은 세부 사항과 함께 "원래"질문에 다시 게시 stackoverflow.com/questions/163162/...
drzaus

6

기억하기 쉽고 게으른 아마도 불완전한 해결책 :

Directory.GetFiles(dir, "*.dll").Union(Directory.GetFiles(dir, "*.exe"))

4

다음을 사용합니다.

var ext = new string[] { ".ASPX", ".ASCX" };
FileInfo[] collection = (from fi in new DirectoryInfo(path).GetFiles()
                         where ext.Contains(fi.Extension.ToUpper())
                         select fi)
                         .ToArray();

편집 : Directory와 DirectoryInfo 간의 불일치 수정


3

파일 시스템을 여러 번 쿼리하지 않고 원하지 않는 파일을 많이 반환하지 않는 확장명이 ".aspx"및 ".ascx"인 파일을 가져 오는보다 효율적인 방법은 대략적인 검색 패턴을 사용하여 파일을 사전 필터링하는 것입니다. 나중에 결과를 구체화하려면 :

var filteredFiles = Directory.GetFiles(path, "*.as?x")
    .Select(f => f.ToLowerInvariant())
    .Where(f => f.EndsWith("px") || f.EndsWith("cx"))
    .ToList();

2

나는 같은 것을 지정하려고 노력할 것이다.

var searchPattern = "as?x";

작동해야합니다.


하! aspx와 ascx가 너무 비슷하여 해킹 솔루션을 렌더링 할까봐 두려웠습니다. 나는 일반적인 것을 원한다.
Seb Nilsson

2
    /// <summary>
    /// Returns the names of files in a specified directories that match the specified patterns using LINQ
    /// </summary>
    /// <param name="srcDirs">The directories to seach</param>
    /// <param name="searchPatterns">the list of search patterns</param>
    /// <param name="searchOption"></param>
    /// <returns>The list of files that match the specified pattern</returns>
    public static string[] GetFilesUsingLINQ(string[] srcDirs,
         string[] searchPatterns,
         SearchOption searchOption = SearchOption.AllDirectories)
    {
        var r = from dir in srcDirs
                from searchPattern in searchPatterns
                from f in Directory.GetFiles(dir, searchPattern, searchOption)
                select f;

        return r.ToArray();
    }

2
    public static bool CheckFiles(string pathA, string pathB)
    {
        string[] extantionFormat = new string[] { ".war", ".pkg" };
        return CheckFiles(pathA, pathB, extantionFormat);
    }
    public static bool CheckFiles(string pathA, string pathB, string[] extantionFormat)
    {
        System.IO.DirectoryInfo dir1 = new System.IO.DirectoryInfo(pathA);
        System.IO.DirectoryInfo dir2 = new System.IO.DirectoryInfo(pathB);
        // Take a snapshot of the file system. list1/2 will contain only WAR or PKG 
        // files
        // fileInfosA will contain all of files under path directories 
        FileInfo[] fileInfosA = dir1.GetFiles("*.*", 
                              System.IO.SearchOption.AllDirectories);
        // list will contain all of files that have ..extantion[]  
        // Run on all extantion in extantion array and compare them by lower case to 
        // the file item extantion ...
        List<System.IO.FileInfo> list1 = (from extItem in extantionFormat
                                          from fileItem in fileInfosA
                                          where extItem.ToLower().Equals 
                                          (fileItem.Extension.ToLower())
                                          select fileItem).ToList();
        // Take a snapshot of the file system. list1/2 will contain only WAR or  
        // PKG files
        // fileInfosA will contain all of files under path directories 
        FileInfo[] fileInfosB = dir2.GetFiles("*.*", 
                                       System.IO.SearchOption.AllDirectories);
        // list will contain all of files that have ..extantion[]  
        // Run on all extantion in extantion array and compare them by lower case to 
        // the file item extantion ...
        List<System.IO.FileInfo> list2 = (from extItem in extantionFormat
                                          from fileItem in fileInfosB
                                          where extItem.ToLower().Equals            
                                          (fileItem.Extension.ToLower())
                                          select fileItem).ToList();
        FileCompare myFileCompare = new FileCompare();
        // This query determines whether the two folders contain 
        // identical file lists, based on the custom file comparer 
        // that is defined in the FileCompare class. 
        return list1.SequenceEqual(list2, myFileCompare);
    }

2

EndsWith 함수 Path.GetExtension()대신 메소드를 대신 사용하도록 선택합니다 . 전체 예는 다음과 같습니다.

var filteredFiles = Directory.EnumerateFiles( path )
.Where(
    file => Path.GetExtension(file).Equals( ".aspx", StringComparison.OrdinalIgnoreCase ) ||
            Path.GetExtension(file).Equals( ".ascx", StringComparison.OrdinalIgnoreCase ) );

또는:

var filteredFiles = Directory.EnumerateFiles(path)
.Where(
    file => string.Equals( Path.GetExtension(file), ".aspx", StringComparison.OrdinalIgnoreCase ) ||
            string.Equals( Path.GetExtension(file), ".ascx", StringComparison.OrdinalIgnoreCase ) );

( StringComparison.OrdinalIgnoreCase성능에 관심이있는 경우 사용 : MSDN 문자열 비교 )


1

이 데모처럼 보입니다 :

void Main()
{
    foreach(var f in GetFilesToProcess("c:\\", new[] {".xml", ".txt"}))
        Debug.WriteLine(f);
}
private static IEnumerable<string> GetFilesToProcess(string path, IEnumerable<string> extensions)
{
   return Directory.GetFiles(path, "*.*")
       .Where(f => extensions.Contains(Path.GetExtension(f).ToLower()));
}

1
당신은 Path.GetExtension당신이 사용할 수있다.
jgauffin

1

@Daniel B,이 함수의 내 자신의 버전을 작성하도록 제안 해 주셔서 감사합니다. Directory.GetFiles와 동일하게 작동하지만 정규식 필터링을 지원합니다.

string[] FindFiles(FolderBrowserDialog dialog, string pattern)
    {
        Regex regex = new Regex(pattern);

        List<string> files = new List<string>();
        var files=Directory.GetFiles(dialog.SelectedPath);
        for(int i = 0; i < files.Count(); i++)
        {
            bool found = regex.IsMatch(files[i]);
            if(found)
            {
                files.Add(files[i]);
            }
        }

        return files.ToArray();
    }

나는 그것이 유용하다는 것을 알았으므로 공유 할 것이라고 생각했다.


1

@ qfactor77의 대답의 C # 버전. 이것은 LINQ없이 가장 좋은 방법입니다.

string[] wildcards= {"*.mp4", "*.jpg"};
ReadOnlyCollection<string> filePathCollection = FileSystem.GetFiles(dirPath, Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, wildcards);
string[] filePath=new string[filePathCollection.Count];
filePathCollection.CopyTo(filePath,0);

이제 filePath문자열 배열을 반환 합니다. 처음에는 당신이 필요

using Microsoft.VisualBasic.FileIO;
using System.Collections.ObjectModel;

또한 당신은 참조를 추가해야합니다 Microsoft.VisualBasic


1

필요한만큼의 확장 프로그램을 검색하고 ToLower (), RegEx, foreach를 사용하지 않는 간단한 방법을 사용했습니다.

List<String> myExtensions = new List<String>() { ".aspx", ".ascx", ".cs" }; // You can add as many extensions as you want.
DirectoryInfo myFolder = new DirectoryInfo(@"C:\FolderFoo");
SearchOption option = SearchOption.TopDirectoryOnly; // Use SearchOption.AllDirectories for seach in all subfolders.
List<FileInfo> myFiles = myFolder.EnumerateFiles("*.*", option)
    .Where(file => myExtensions
    .Any(e => String.Compare(file.Extension, e, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase) == 0))
    .ToList();

.Net Standard 2.0 작업.


1

당신은 이렇게 할 수 있습니다

new DirectoryInfo(path).GetFiles().Where(Current => Regex.IsMatch(Current.Extension, "\\.(aspx|ascx)", RegexOptions.IgnoreCase)

문제는 : LINQ는 옵션이 아니므로이 답변은 유용하지 않습니다
Arci

0
var filtered = Directory.GetFiles(path)
    .Where(file => file.EndsWith("aspx", StringComparison.InvariantCultureIgnoreCase) || file.EndsWith("ascx", StringComparison.InvariantCultureIgnoreCase))
    .ToList();

코드에 대한 추가 설명을 추가하십시오. OP가 답변을 더 잘 이해하는 데 도움이 될 수 있습니다.
user2339071

-2

FileIO.FileSystem.GetFiles대신에 대신 사용하면Directory.GetFiles 와일드 카드 배열이 허용 .

예를 들면 다음과 같습니다.

Dim wildcards As String() = {"*.html", "*.zip"}
Dim ListFiles As List(Of String) = FileIO.FileSystem.GetFiles(directoryyouneed, FileIO.SearchOption.SearchTopLevelOnly, wildcards).ToList

어디서 구할 수 FileIO있습니까?
Joel Martinez

1
Visual Studio (2015)의 환경에 이미 포함되어 있어야합니다. Microsoft.VisualBasic 네임 스페이스의 일부입니다. 필자의 경우 선택한 언어이기 때문에 VisualBasic입니다.
qfactor77
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.