web-dev-qa-db-ja.com

ディレクトリ内のファイルを再帰的に検索する

ディレクトリを介してファイルを再帰的に検索する次のコードがあり、すべてのxmlファイルのリストが返されます。ルートディレクトリ内のxmlファイルがリストに含まれていないことを除いて、すべて正常に機能します。

最初に行うのはルートのディレクトリを取得し、次にファイルを取得することであるため、ルートのGetFiles()呼び出しが欠落している理由を理解しています。 foreachの前にGetFiles()呼び出しを含めてみましたが、結果は期待どおりではありません。

public static ArrayList DirSearch(string sDir)
{
    try
    {
        foreach (string d in Directory.GetDirectories(sDir))
        {
            foreach (string f in Directory.GetFiles(d, "*.xml"))
            {
                string extension = Path.GetExtension(f);
                if (extension != null && (extension.Equals(".xml")))
                {
                fileList.Add(f);
                }
            }
            DirSearch(d);
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
    return fileList;
}

私のディレクトリ構造は次のようなものです:

RootDirectory
        test1.0.xml
            test1.1.xml
            test1.2.xml
  2ndLevDir
            test2.0.xml
            test2.1.xml
  3rdLevDir
               test3.0.xml
               test3.1.xml

コードの戻り値:

test2.0.xml
test2.1.xml
test3.0.xml
test3.1.xml

以下を含むすべてのファイルを返したい:

test1.0.xml
test1.1.xml
test1.2.xml

再帰ではあまりよくありません。どんなポインタでも大歓迎です。

54
Paul

Directory.GetFilesのこのオーバーロード を使用して、サブディレクトリを検索できます。例:

string[] files = Directory.GetFiles(sDir, "*.xml", SearchOption.AllDirectories);

そのように検索できる拡張子は1つだけですが、次のようなものを使用できます。

var extensions = new List<string> { ".txt", ".xml" };
string[] files = Directory.GetFiles(sDir, "*.*", SearchOption.AllDirectories)
                    .Where(f => extensions.IndexOf(Path.GetExtension(f)) >= 0).ToArray();

必要な拡張子を持つファイルを選択します(拡張子の大文字と小文字が区別されるN.B.)。


Directory.EnumerateFiles Method を使用してファイルを列挙することが望ましい場合があります。

foreach(string f in Directory.EnumerateFiles(sDir, "*.xml", SearchOption.AllDirectories))
{
    // do something
}

適切なアクセス許可を持たないアカウントでコードが実行されている場合、UnauthorizedAccessExceptionなど、スローされる可能性がある例外については、ドキュメントを参照してください。

104
Andrew Morton

これにより、すべてのxmlファイルが再帰的に返されます。

var allFiles = Directory.GetFiles(path, "*.xml", SearchOption.AllDirectories);
49
Tim Schmelter

次の方法を試してください。

public static IEnumerable<string> GetXMLFiles(string directory)
{
    List<string> files = new List<string>();

    try
    {
        files.AddRange(Directory.GetFiles(directory, "*.xml", SearchOption.AllDirectories));
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }

    return files;
}
3
Bernard

1つを使用する代わりに、3つのリストを作成しています(DirSearch(d)の戻り値は使用しません)。リストをパラメーターとして使用して、状態を保存できます。

static void Main(string[] args)
{
  var list = new List<string>();
  DirSearch(list, ".");

  foreach (var file in list)
  {
    Console.WriteLine(file);
  }
}

public static void DirSearch(List<string> files, string startDirectory)
{
  try
  {
    foreach (string file in Directory.GetFiles(startDirectory, "*.*"))
    {
      string extension = Path.GetExtension(file);

      if (extension != null)
      {
        files.Add(file);
      }
    }

    foreach (string directory in Directory.GetDirectories(startDirectory))
    {
      DirSearch(files, directory);
    }
  }
  catch (System.Exception e)
  {
    Console.WriteLine(e.Message);
  }
}
3
Gene

ディレクトリのループの前または後にファイルのループを作成する必要がありますが、これまでのようにファイル内にネストすることはできません。

foreach (string f in Directory.GetFiles(d, "*.xml"))
{
    string extension = Path.GetExtension(f);
    if (extension != null && (extension.Equals(".xml")))
    {
        fileList.Add(f);
    }
} 

foreach (string d in Directory.GetDirectories(sDir))
{
    DirSearch(d);
}
3
Mark Byers

次のようなことができます:

foreach (var file in Directory.GetFiles(MyFolder, "*.xml", SearchOption.AllDirectories))
        {
            // do something with this file
        }
2
damir

フォルダーのループの外側にファイルのループを移動する必要があります。さらに、ファイルのコレクションを保持するデータ構造をメソッドの各呼び出しに渡す必要があります。これにより、すべてのファイルが単一のリストに入れられます。

public static List<string> DirSearch(string sDir, List<string> files)
{
  foreach (string f in Directory.GetFiles(sDir, "*.xml"))
  {
    string extension = Path.GetExtension(f);
    if (extension != null && (extension.Equals(".xml")))
    {
      files.Add(f);
    }
  }
  foreach (string d in Directory.GetDirectories(sDir))
  {
    DirSearch(d, files);
  }
  return files;
}

次に、このように呼び出します。

List<string> files = DirSearch("c:\foo", new List<string>());

更新:

とにかく他の答えを読むまで、これを行うための組み込みのメカニズムが既にあります。コードを機能させるためにどのようにコードを変更する必要があるかを知りたい場合は、回答を残します。

1
Brian Gideon

EnumerateFilesを使用して、ネストされたディレクトリ内のファイルを取得します。 AllDirectoriesを使用して、ディレクトリ全体を再帰します。

using System;
using System.IO;

class Program
{
    static void Main()
    {
    // Call EnumerateFiles in a foreach-loop.
    foreach (string file in Directory.EnumerateFiles(@"c:\files",
        "*.xml",
        SearchOption.AllDirectories))
    {
        // Display file path.
        Console.WriteLine(file);
    }
    }
}
0
mercedes