System.IO.Directory.GetFilesの複数のファイル拡張子searchPattern


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ます。


あるとは思いません。すべてのファイルをリストしてから手動でフィルタリングするか、複数のサーチャーで結合を実行します。しかし、SOでこの正確な質問を見たことがあると私はかなり確信しています。
CodesInChaos


以前はここで尋ねたと答えた:stackoverflow.com/questions/163162/...
デヴィッド・

回答:


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

190
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 2011

4
EndsWith()引数から*を削除する必要があります。ワイルドカードの一致は行われません。
ハンスパッサント

3
ファイルの拡張子を比較すると、 '。Where(file => new FileInfo(file).Extension.Equals( "。aspx")|| new FileInfo(file).Extension.Equals( "。ascx")のような完全一致を返します。 ) '
ダミス

3
新しい.NET4を忘れてはいけないDirectory.EnumerateFilesパフォーマンスの向上のために... 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>。前者を行うように編集されました。
ブライアン

私は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

@ジョドレル、または単にaHashSet<string>
ジョドレル

拡張の数が制限されており、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();

これは良いアプローチのようです。欠けている部分は、テストされた(動作する)正規表現を持つことです
JuniorMayhéAug

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 2013年

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 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.