395

Directory.GetFiles()メソッドを使用して、 や などの複数のタイプのファイルのリストを取得mp3しようとしていますjpg。私は運がないので、次の両方を試しました:

Directory.GetFiles("C:\\path", "*.mp3|*.jpg", SearchOption.AllDirectories);
Directory.GetFiles("C:\\path", "*.mp3;*.jpg", SearchOption.AllDirectories);

1回の呼び出しでこれを行う方法はありますか?

4

26 に答える 26

587

.NET 4.0 以降の場合、

var files = Directory.EnumerateFiles("C:\\path", "*.*", SearchOption.AllDirectories)
            .Where(s => s.EndsWith(".mp3") || s.EndsWith(".jpg"));

以前のバージョンの .NET では、

var files = Directory.GetFiles("C:\\path", "*.*", SearchOption.AllDirectories)
            .Where(s => s.EndsWith(".mp3") || s.EndsWith(".jpg"));

編集: コメントを読んでください。Paul Farryが提案する改善と、 Christian.Kが指摘するメモリ/パフォーマンスの問題は、どちらも非常に重要です。

于 2008-10-02T16:09:11.927 に答える
67

これはどう:

private static string[] GetFiles(string sourceFolder, string filters, System.IO.SearchOption searchOption)
{
   return filters.Split('|').SelectMany(filter => System.IO.Directory.GetFiles(sourceFolder, filter, searchOption)).ToArray();
}

ここで見つけました(コメントで):http://msdn.microsoft.com/en-us/library/wz42302f.aspx

于 2011-12-11T19:55:28.967 に答える
36

チェックする拡張機能のリストが多数ある場合は、次を使用できます。OR ステートメントをたくさん作成したくなかったので、lette が書いたものを修正しました。

string supportedExtensions = "*.jpg,*.gif,*.png,*.bmp,*.jpe,*.jpeg,*.wmf,*.emf,*.xbm,*.ico,*.eps,*.tif,*.tiff,*.g01,*.g02,*.g03,*.g04,*.g05,*.g06,*.g07,*.g08";
foreach (string imageFile in Directory.GetFiles(_tempDirectory, "*.*", SearchOption.AllDirectories).Where(s => supportedExtensions.Contains(Path.GetExtension(s).ToLower())))
{
    //do work here
}
于 2011-01-06T16:36:58.490 に答える
34

為に

var exts = new[] { "mp3", "jpg" };

あなたは出来る:

public IEnumerable<string> FilterFiles(string path, params string[] exts) {
    return
        Directory
        .EnumerateFiles(path, "*.*")
        .Where(file => exts.Any(x => file.EndsWith(x, StringComparison.OrdinalIgnoreCase)));
}

しかし、フィルターを分割して結果をマージすると、 の本当の利点がEnumerateFiles現れます。

public IEnumerable<string> FilterFiles(string path, params string[] exts) {
    return 
        exts.Select(x => "*." + x) // turn into globs
        .SelectMany(x => 
            Directory.EnumerateFiles(path, x)
            );
}

それらをグロブに変換する必要がない場合(つまり、exts = new[] {"*.mp3", "*.jpg"}すでに)、少し速くなります。

次の LinqPad テストに基づくパフォーマンス評価 (注:Perfデリゲートを 10000 回繰り返すだけです) https://gist.github.com/zaus/7454021

(その質問は特にLINQを要求しなかったため、「重複」から再投稿および拡張されました:System.IO.Directory.GetFilesの複数のファイル拡張子searchPattern

于 2013-11-13T18:39:15.773 に答える
18

古い質問だと思いますが、LINQ: (.NET40+)

var files = Directory.GetFiles("path_to_files").Where(file => Regex.IsMatch(file, @"^.+\.(wav|mp3|txt)$"));
于 2012-10-17T04:18:10.573 に答える
15

メモリやパフォーマンスのオーバーヘッドがなく、非常にエレガントな降下ソリューションもあります。

string[] filters = new[]{"*.jpg", "*.png", "*.gif"};
string[] filePaths = filters.SelectMany(f => Directory.GetFiles(basePath, f)).ToArray();
于 2013-03-22T13:03:58.223 に答える
12

Linqを使用する別の方法ですが、すべてを返し、メモリ内でフィルタリングする必要はありません。

var files = Directory.GetFiles("C:\\path", "*.mp3", SearchOption.AllDirectories).Union(Directory.GetFiles("C:\\path", "*.jpg", SearchOption.AllDirectories));

実際には2回の呼び出しGetFiles()ですが、質問の精神と一致しており、1つの列挙可能なものに返されます。

于 2011-12-02T22:31:33.177 に答える
8

させて

var set = new HashSet<string> { ".mp3", ".jpg" };

それで

Directory.GetFiles(path, "*.*", SearchOption.AllDirectories)
         .Where(f => set.Contains(
             new FileInfo(f).Extension,
             StringComparer.OrdinalIgnoreCase));

また

from file in Directory.GetFiles(path, "*.*", SearchOption.AllDirectories)
from ext in set
where String.Equals(ext, new FileInfo(file).Extension, StringComparison.OrdinalIgnoreCase)
select file;
于 2010-09-14T08:16:22.763 に答える
7

いいえ。次のことを試してください。

List<string> _searchPatternList = new List<string>();
    ...
    List<string> fileList = new List<string>();
    foreach ( string ext in _searchPatternList )
    {
        foreach ( string subFile in Directory.GetFiles( folderName, ext  )
        {
            fileList.Add( subFile );
        }
    }

    // Sort alpabetically
    fileList.Sort();

    // Add files to the file browser control    
    foreach ( string fileName in fileList )
    {
        ...;
    }

出典: http://blogs.msdn.com/markda/archive/2006/04/20/580075.aspx

于 2008-10-02T16:06:20.263 に答える
5

.NET Framework 2.0 でプログラミングしているため、メソッドを使用できません.Where(Linq は .NET Framework 3.5+ でのみサポートされています)。

以下のコードは大文字と小文字を区別しません (したがって、.CaBまたは.cabリストにも表示されます)。

string[] ext = new string[2] { "*.CAB", "*.MSU" };

foreach (string found in ext)
{
    string[] extracted = Directory.GetFiles("C:\\test", found, System.IO.SearchOption.AllDirectories);

    foreach (string file in extracted)
    {
        Console.WriteLine(file);
    }
}
于 2011-11-26T17:02:46.113 に答える
4

The following function searches on multiple patterns, separated by commas. You can also specify an exclusion, eg: "!web.config" will search for all files and exclude "web.config". Patterns can be mixed.

private string[] FindFiles(string directory, string filters, SearchOption searchOption)
{
    if (!Directory.Exists(directory)) return new string[] { };

    var include = (from filter in filters.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries) where !string.IsNullOrEmpty(filter.Trim()) select filter.Trim());
    var exclude = (from filter in include where filter.Contains(@"!") select filter);

    include = include.Except(exclude);

    if (include.Count() == 0) include = new string[] { "*" };

    var rxfilters = from filter in exclude select string.Format("^{0}$", filter.Replace("!", "").Replace(".", @"\.").Replace("*", ".*").Replace("?", "."));
    Regex regex = new Regex(string.Join("|", rxfilters.ToArray()));

    List<Thread> workers = new List<Thread>();
    List<string> files = new List<string>();

    foreach (string filter in include)
    {
        Thread worker = new Thread(
            new ThreadStart(
                delegate
                {
                    string[] allfiles = Directory.GetFiles(directory, filter, searchOption);
                    if (exclude.Count() > 0)
                    {
                        lock (files)
                            files.AddRange(allfiles.Where(p => !regex.Match(p).Success));
                    }
                    else
                    {
                        lock (files)
                            files.AddRange(allfiles);
                    }
                }
            ));

        workers.Add(worker);

        worker.Start();
    }

    foreach (Thread worker in workers)
    {
        worker.Join();
    }

    return files.ToArray();

}

Usage:

foreach (string file in FindFiles(@"D:\628.2.11", @"!*.config, !*.js", SearchOption.AllDirectories))
            {
                Console.WriteLine(file);
            }
于 2010-05-31T17:43:28.413 に答える
4
DirectoryInfo directory = new DirectoryInfo(Server.MapPath("~/Contents/"));

//Using Union

FileInfo[] files = directory.GetFiles("*.xlsx")
                            .Union(directory
                            .GetFiles("*.csv"))
                            .ToArray();
于 2013-04-19T09:40:18.050 に答える
4
List<string> FileList = new List<string>();
DirectoryInfo di = new DirectoryInfo("C:\\DirName");

IEnumerable<FileInfo> fileList = di.GetFiles("*.*");

//Create the query
IEnumerable<FileInfo> fileQuery = from file in fileList
                                  where (file.Extension.ToLower() == ".jpg" || file.Extension.ToLower() == ".png")
                                  orderby file.LastWriteTime
                                  select file;

foreach (System.IO.FileInfo fi in fileQuery)
{
    fi.Attributes = FileAttributes.Normal;
    FileList.Add(fi.FullName);
}
于 2010-09-18T04:37:25.643 に答える
4

.NET 2.0 (Linq なし):

public static List<string> GetFilez(string path, System.IO.SearchOption opt,  params string[] patterns)
{
    List<string> filez = new List<string>();
    foreach (string pattern in patterns)
    {
        filez.AddRange(
            System.IO.Directory.GetFiles(path, pattern, opt)
        );
    }


    // filez.Sort(); // Optional
    return filez; // Optional: .ToArray()
}

次に、それを使用します。

foreach (string fn in GetFilez(path
                             , System.IO.SearchOption.AllDirectories
                             , "*.xml", "*.xml.rels", "*.rels"))
{}
于 2014-09-03T11:31:49.337 に答える
3

それを行う別の方法を見つけただけです。まだ1つの操作ではありませんが、他の人がそれについてどう思うかを見るためにそれを捨てています.

private void getFiles(string path)
{
    foreach (string s in Array.FindAll(Directory.GetFiles(path, "*", SearchOption.AllDirectories), predicate_FileMatch))
    {
        Debug.Print(s);
    }
}

private bool predicate_FileMatch(string fileName)
{
    if (fileName.EndsWith(".mp3"))
        return true;
    if (fileName.EndsWith(".jpg"))
        return true;
    return false;
}
于 2008-10-02T17:17:32.183 に答える
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();
}
于 2011-12-15T07:27:34.730 に答える
2

なぜこんなに多くの「解決策」が投稿されているのだろうか?

GetFiles がどのように機能するかについての私の初心者の理解が正しければ、2 つのオプションしかなく、上記の解決策のいずれかをこれらにまとめることができます。

  1. GetFiles、次にフィルタ: 高速ですが、フィルタが適用されるまでオーバーヘッドを格納するためメモリ キラー

  2. GetFiles 中のフィルター: 設定するフィルターが多いほど遅くなりますが、オーバーヘッドが保存されないため、メモリ使用量は少なくなります。
    これは、上記の投稿の 1 つで印象的なベンチマークで説明されています。各フィルター オプションは個別の GetFile 操作を引き起こすため、ハード ドライブの同じ部分が数回読み取られます。

私の意見では、オプション 1) の方が優れていますが、C:\ などのフォルダーで SearchOption.AllDirectories を使用すると、大量のメモリが使用されます。
したがって、オプション1を使用してすべてのサブフォルダーを通過する再帰的なサブメソッドを作成するだけです)

これにより、各フォルダーで 1 つの GetFiles 操作のみが発生するため、高速になりますが (オプション 1)、各サブフォルダーの読み取り後にフィルターが適用されるため、少量のメモリしか使用しません -> 各サブフォルダーの後にオーバーヘッドが削除されます。

間違っている場合は修正してください。私が言ったように、私はプログラミングにまったく慣れていませんが、最終的にこれが得意になるために物事をより深く理解したいと思っています:)

于 2013-04-02T15:32:10.607 に答える
2

いいえ...必要なファイルタイプと同じ数の呼び出しを行う必要があると思います。

必要な拡張機能を備えた文字列の配列を取得する関数を自分で作成し、その配列を反復処理して必要なすべての呼び出しを行います。その関数は、私が送信した拡張子に一致するファイルの一般的なリストを返します。

それが役に立てば幸い。

于 2008-10-02T16:09:01.380 に答える
2

必要な拡張子を 1 つの文字列、つまり ".mp3.jpg.wma.wmf" にしてから、各ファイルに必要な拡張子が含まれているかどうかを確認します。LINQ を使用しないため、これは .net 2.0 で機能します。

string myExtensions=".jpg.mp3";

string[] files=System.IO.Directory.GetFiles("C:\myfolder");

foreach(string file in files)
{
   if(myExtensions.ToLower().contains(System.IO.Path.GetExtension(s).ToLower()))
   {
      //this file has passed, do something with this file

   }
}

このアプローチの利点は、コードを編集せずに拡張子を追加または削除できることです。つまり、png 画像を追加するには、myExtensions=".jpg.mp3.png" と書くだけです。

于 2012-04-02T22:24:40.257 に答える
2

フィルタリングされたファイルを取得するシンプルでエレガントな方法は次のとおりです

var allowedFileExtensions = ".csv,.txt";


var files = Directory.EnumerateFiles(@"C:\MyFolder", "*.*", SearchOption.TopDirectoryOnly)
                .Where(s => allowedFileExtensions.IndexOf(Path.GetExtension(s)) > -1).ToArray(); 
于 2020-06-12T10:50:12.070 に答える
1

私は同じ問題を抱えていて、適切な解決策を見つけることができなかったので、GetFiles という関数を書きました。

/// <summary>
/// Get all files with a specific extension
/// </summary>
/// <param name="extensionsToCompare">string list of all the extensions</param>
/// <param name="Location">string of the location</param>
/// <returns>array of all the files with the specific extensions</returns>
public string[] GetFiles(List<string> extensionsToCompare, string Location)
{
    List<string> files = new List<string>();
    foreach (string file in Directory.GetFiles(Location))
    {
        if (extensionsToCompare.Contains(file.Substring(file.IndexOf('.')+1).ToLower())) files.Add(file);
    }
    files.Sort();
    return files.ToArray();
}

この関数はDirectory.Getfiles()1 回だけ呼び出されます。

たとえば、次のように関数を呼び出します。

string[] images = GetFiles(new List<string>{"jpg", "png", "gif"}, "imageFolder");

編集: 複数の拡張子を持つ 1 つのファイルを取得するには、次のファイルを使用します。

/// <summary>
    /// Get the file with a specific name and extension
    /// </summary>
    /// <param name="filename">the name of the file to find</param>
    /// <param name="extensionsToCompare">string list of all the extensions</param>
    /// <param name="Location">string of the location</param>
    /// <returns>file with the requested filename</returns>
    public string GetFile( string filename, List<string> extensionsToCompare, string Location)
    {
        foreach (string file in Directory.GetFiles(Location))
        {
            if (extensionsToCompare.Contains(file.Substring(file.IndexOf('.') + 1).ToLower()) &&& file.Substring(Location.Length + 1, (file.IndexOf('.') - (Location.Length + 1))).ToLower() == filename) 
                return file;
        }
        return "";
    }

たとえば、次のように関数を呼び出します。

string image = GetFile("imagename", new List<string>{"jpg", "png", "gif"}, "imageFolder");
于 2012-12-05T08:39:34.537 に答える
0

拡張子のフィルタリングに GetFiles 検索パターンを使用するのは安全ではありません!! たとえば、Test1.xls と Test2.xlsx の 2 つのファイルがあり、検索パターン *.xls を使用して xls ファイルを除外したいが、GetFiles が Test1.xls と Test2.xlsx の両方を返すとします。一部の一時ファイルが突然正しいファイルとして扱われる環境。検索パターンは *.txt で、一時ファイルの名前は *.txt20181028_100753898 なので、検索パターンは信頼できないため、ファイル名にも追加のチェックを追加する必要があります。

于 2018-11-06T11:34:50.173 に答える
-1

または、拡張子の文字列を String^ に変換することもできます

vector <string>  extensions = { "*.mp4", "*.avi", "*.flv" };
for (int i = 0; i < extensions.size(); ++i)
{
     String^ ext = gcnew String(extensions[i].c_str());;
     String^ path = "C:\\Users\\Eric\\Videos";
     array<String^>^files = Directory::GetFiles(path,ext);
     Console::WriteLine(ext);
     cout << " " << (files->Length) << endl;
}
于 2014-04-08T20:51:01.680 に答える