161 votes

Modèle de recherche d'extensions de fichiers multiples pour System.IO.Directory.GetFiles

Quelle est la syntaxe pour définir Extensions de fichiers multiples comme searchPattern en Directory.GetFiles() ? Par exemple, en filtrant les fichiers contenant .aspx y .ascx extensions.

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

Mise à jour : LINQ n'est pas une option il faut que ce soit un searchPattern passé dans GetFiles comme indiqué dans la question.

0 votes

Je ne pense pas qu'il y en ait. Il faut soit lister tous les fichiers et ensuite filtrer manuellement, soit effectuer une union sur plusieurs chercheurs. Mais je suis presque sûr d'avoir déjà vu cette question exacte sur SO.

1 votes

0 votes

Question précédemment posée et réponse ici : stackoverflow.com/questions/163162/

199voto

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

Edition 2014-07-23

Vous pouvez le faire dans .NET 4.5 pour une énumération plus rapide :

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

Directory.EnumerateFiles dans MSDN

0 votes

+1 m'a devancé :) est-ce que le double tuyau a besoin d'un autre support pour l'entourer ?

0 votes

Vous êtes sûr que c'est correct ? La méthode GetFiles renvoie un tableau d'objets FileInfo, et non des chaînes de caractères. Comment pouvez-vous appliquer la méthode EndsWith ?

5 votes

@Mario Vernari : GetFiles renvoie à string[] .

45voto

Daniel B Points 1789

Je crois qu'il n'y a pas de solution "toute faite", c'est une limitation de la méthode Directory.GetFiles.

Il est cependant assez facile d'écrire votre propre méthode. exemple .

Le code pourrait être :

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

9 votes

Cette façon de faire est très insuffisante, puisque vous allez boucler un répertoire entier pour chaque filtre. Au lieu de cela, vous devriez vérifier pour chaque fichier s'il possède le filtre puis l'ajouter à la liste. Vous pouvez utiliser la réponse expliquée dans ce fil : stackoverflow.com/questions/3754118/

31voto

Ulrik Magnusson Points 231

GetFiles ne peut correspondre qu'à un seul motif, mais vous pouvez utiliser Linq pour invoquer GetFiles avec plusieurs motifs :

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

Voir la section des commentaires ici : http://www.codeproject.com/KB/aspnet/NET_DirectoryInfo.aspx

2 votes

Ils entreront en collision si les motifs se chevauchent. Par exemple, new string[]{"*.txt","filename.*"} . Cependant, l'appel à Distinct ne résout pas réellement ce problème, puisque les objets FileInfo comparent en utilisant l'égalité de référence, et non l'égalité sémantique. Ce problème pourrait être résolu soit en supprimant l'élément Distinct ou en lui passant un IEqualityComparer<FileInfo> . Modifié pour faire le premier.

0 votes

Je pense que SelectMany itérera sur la même structure de fichier encore (et encore), ce qui pourrait être sous-optimal en termes de performances.

16voto

drzaus Points 3344
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();

Ou bien, il peut être plus rapide de diviser et de fusionner vos globs (au moins, cela semble plus propre) :

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

0 votes

Et de reposter sur la question "originale" avec plus de détails -- stackoverflow.com/questions/163162/

15voto

Jodrell Points 14205

Je crains que vous ne deviez faire quelque chose comme ceci, j'ai muté la regex de aquí .

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

0 votes

Cela semble être une bonne approche, la partie manquante est d'avoir une expression régulière testée (qui fonctionne).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X