web-dev-qa-db-fra.com

Recherche de fichier dans les répertoires de manière récursive

J'ai le code suivant pour rechercher de manière récursive des fichiers dans un répertoire, ce qui me renvoie la liste de tous les fichiers xml. Tout fonctionne bien, sauf que les fichiers XML du répertoire racine ne sont pas inclus dans la liste.

Je comprends pourquoi, puisque la première chose à faire est d’obtenir les répertoires à la racine, puis les fichiers, manquant ainsi l’appel GetFiles () sur la racine. J'ai essayé d'inclure l'appel GetFiles () avant le foreach, mais les résultats ne sont pas ceux que je prévois. 

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;
}

Ma structure de répertoire est quelque chose comme:

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

Le code retourne:

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

J'aimerais retourner tous les fichiers, y compris:

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

Pas très bien vers avec récurrence. Tous les indicateurs seraient grandement appréciés.

46
Paul

Vous pouvez utiliser cette surcharge de Directory.GetFiles qui recherche pour vous des sous-répertoires, par exemple:

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

Une seule extension peut être recherchée comme ça, mais vous pouvez utiliser quelque chose comme:

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

sélectionner des fichiers avec les extensions requises (NB, sensible à la casse pour l’extension).


Dans certains cas, il peut être souhaitable d’énumérer les fichiers avec la méthode Directory.EnumerateFiles :

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

Consultez la documentation pour connaître les exceptions pouvant être levées, telles que UnauthorizedAccessException si le code est exécuté sous un compte ne disposant pas des autorisations d'accès appropriées.

87
Andrew Morton

Cela retourne tous les fichiers XML de manière récursive:

var allFiles = Directory.GetFiles(path, "*.xml", SearchOption.AllDirectories);
46
Rango

Essayez la méthode suivante:

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

Vous créez trois listes au lieu d’en utiliser une (vous n’utilisez pas la valeur de retour de DirSearch(d)). Vous pouvez utiliser une liste en tant que paramètre pour enregistrer l'état:

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

Vous devriez avoir la boucle sur les fichiers avant ou après la boucle sur les répertoires, mais pas imbriquée à l'intérieur comme vous l'avez fait.

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

vous pouvez faire quelque chose comme ça: 

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

Vous voudrez déplacer la boucle pour les fichiers en dehors de la boucle pour les dossiers. De plus, vous devrez transmettre la structure de données contenant la collection de fichiers à chaque appel de la méthode. Ainsi, tous les fichiers sont regroupés dans une seule liste.

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;
}

Alors appelle ça comme ça.

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

Mettre à jour:

À l'insu de moi, jusqu'à ce que je lise l'autre réponse de toute façon, il existe déjà un mécanisme intégré pour le faire. Je laisserai ma réponse au cas où vous voudriez savoir comment votre code doit être modifié pour le faire fonctionner.

1
Brian Gideon

Utiliser EnumerateFiles pour obtenir des fichiers dans des répertoires imbriqués. Utilisez AllDirectories pour recurse dans des répertoires.

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