Können Sie Directory.GetFiles () mit mehreren Filtern aufrufen?

353

Ich versuche, die Directory.GetFiles()Methode zu verwenden, um eine Liste von Dateien verschiedener Typen abzurufen, z. B. mp3's und jpg' s. Ich habe beide der folgenden ohne Glück versucht:

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

Gibt es eine Möglichkeit, dies in einem Anruf zu tun?

Jason Z.
quelle
3
Nebenbei bemerkt, die Verwendung des GetFiles-Suchmusters zum Filtern der Erweiterung ist nicht sicher. Beispielsweise haben Sie zwei Dateien Test1.xls und Test2.xlsx und möchten die xls-Datei mithilfe des Suchmusters * .xls herausfiltern, GetFiles gibt jedoch beide Test1 zurück .xls und Test2.xlsx. Lesen Sie Hinweis Abschnitt für weitere Informationen
Kiran
Wie kann man das verhindern?
Klammern
2
@ kiran Wie ist das nicht sicher? Das sieht eher nach einer Funktion als nach einem Fehler aus.
Kyle Delaney

Antworten:

519

Für .NET 4.0 und höher

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

Für frühere Versionen von .NET

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

bearbeiten: Bitte lesen Sie die Kommentare. Die von Paul Farry vorgeschlagene Verbesserung und das von Christian.K hervorgehobene Gedächtnis- / Leistungsproblem sind beide sehr wichtig.

Christoffer Lette
quelle
10
Mann, ich muss öfter in Bezug auf LINQ denken. Schöne Lösung!
Ken Pespisa
61
Stellen Sie jedoch sicher, dass Sie die Auswirkungen verstehen: Dadurch werden alle Dateien in einem String-Array zurückgegeben und anschließend nach den von Ihnen angegebenen Erweiterungen gefiltert. Dies ist möglicherweise kein großes Problem, wenn "C: \ Path" nicht viele Dateien enthält, aber möglicherweise ein Speicher- / Leistungsproblem bei "C: \" oder ähnlichem.
Christian.K
24
... 2 Jahre später: Netter Code, aber pass auf, wenn du eine Datei hast, die mit .JPG endet, wird sie es nicht schaffen. Besser hinzufügens.ToLower().Endswith...
Stormenet
107
Sie könnten nur verwendens.EndsWith(".mp3", StringComparison.OrdinalIgnoreCase)
Paul Farry
119
Beachten Sie, dass mit .NET 4.0, Sie ersetzen können Directory.GetFilesmit Directory.EnumerateFiles, msdn.microsoft.com/en-us/library/dd383571.aspx , die die Speicherprobleme zu vermeiden , dass @ Christian.K erwähnt.
Jim Mischel
60

Wie wäre es damit:

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

Ich habe es hier gefunden (in den Kommentaren): http://msdn.microsoft.com/en-us/library/wz42302f.aspx

Albert
quelle
Ich vermute, dies vermeidet die potenziellen Speicherprobleme der am besten bewerteten Antwort. In diesem Fall sollte es höher bewertet werden!
Dan W
11
@DanW Die am besten bewertete Antwort belastet sicherlich den Speicher, aber ich denke, das sollte kein solches Problem sein. Ich mochte diese Antwort auch, aber sie ist tatsächlich (viel) langsamer als die akzeptierte Antwort. Überprüfen Sie diesen SpeedTest
OttO
Vielen Dank. Ich bin froh zu sehen, dass es nur etwa doppelt so langsam ist - ich werde in der Zwischenzeit dabei bleiben, denke ich.
Dan W
7
Es ist nur doppelt so langsam, wenn es nur zwei Erweiterungen gibt. Wenn Sie eine Liste mit X-Erweiterungen haben, ist diese X-mal langsamer. Denn hier rufen Sie die Funktion Directory.GetFiles mehrmals auf, während sie in der anderen Lösung nur einmal aufgerufen wird.
Oscar Hermosilla
1
@OscarHermosilla Man kann sie verwenden Parallel.ForEach, um sie parallel zu bekommen
FindOutIslamNow
33

Wenn Sie eine große Liste von zu überprüfenden Erweiterungen haben, können Sie Folgendes verwenden. Ich wollte nicht viele OR-Anweisungen erstellen, also habe ich geändert, was lette geschrieben hat.

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
}
jnoreiga
quelle
Helfen Sie mir bitte dabei ... Wenn ich imageFile drucke, wird der Gesamtpfad angegeben. Wie kann ich es auf den Namen der Datei verkleinern?
Naresh
1
System.IO.Path.GetFileName (imageFile)
jnoreiga
Path.GetExtensionGibt '.ext' zurück, nicht '* .ext' (zumindest in 3.5+).
nullable
2
Zu Ihrer Information: Sie benötigen System.Linq für .where (
jnoreiga
1
Es gibt einen möglichen Fehler. Wir sind längst vorbei, als Erweiterungen genau drei Zeichen lang sein müssen. Angenommen, Sie stoßen auf eine Datei mit .abc, und supportExtensions enthält .abcd. Wird übereinstimmen, sollte es aber nicht. Zu beheben: supportedExtensions = ".jpg|.abcd|";mit .Contains(Path.GetExtension(s).ToLower() + "|"). Nehmen Sie also Ihr Trennzeichen in den Test auf. WICHTIG: Ihr Trennzeichen muss auch nach dem LETZTEN Eintrag in supportExceptions stehen.
ToolmakerSteve
31

zum

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

Du könntest:

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

Der eigentliche Vorteil von EnumerateFileszeigt sich jedoch, wenn Sie die Filter aufteilen und die Ergebnisse zusammenführen:

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

Es wird ein bisschen schneller, wenn Sie sie nicht in Globs verwandeln müssen (dh exts = new[] {"*.mp3", "*.jpg"}bereits).

Leistungsbewertung basierend auf dem folgenden LinqPad-Test (Hinweis: PerfWiederholen Sie den Delegaten nur 10000 Mal) https://gist.github.com/zaus/7454021

(neu gepostet und von 'duplicate' erweitert, da für diese Frage ausdrücklich kein LINQ angefordert wurde: Mehrere Dateierweiterungen searchPattern for System.IO.Directory.GetFiles )

drzaus
quelle
Was meinst du mit "Ich werde ein bisschen schneller, wenn du sie nicht in Globs verwandeln musst"? Ist es O (1) oder ist es O (n) (in Bezug auf die Anzahl der Dateien, nicht in Bezug auf die Anzahl der Erweiterungen)? Ich hätte vermutet, dass es O (1) (oder O (n) in Bezug auf die Anzahl der Erweiterungen) und wahrscheinlich irgendwo im Bereich einiger CPU-Zyklen ist ... Wenn dies der Fall ist, ist es wahrscheinlich - leistungsmäßig - vernachlässigbar
BatteryBackupUnit
@BatteryBackupUnit Ja, mit 10.000 Wiederholungen gegen 2 Erweiterungen beträgt der Unterschied zwischen Glob und Str 3 ms, also technisch gesehen vernachlässigbar (siehe Link zu den Perf-Ergebnissen), aber ich weiß nicht, wie viele Erweiterungen Sie filtern müssen. Ich dachte, es lohnt sich darauf hinzuweisen, dass es eine gibt Unterschied; Ich überlasse es Ihnen zu entscheiden, ob "vereinfachte Verwendung" (dh .FilterFiles(path, "jpg", "gif")) besser ist als "explizite Globs" (dh .FilterFiles(path, "*.jpg", "*.gif")).
Drzaus
perfekt danke. Tut mir leid, dass ich diesen Github-Link irgendwie übersprungen habe. Vielleicht sollte ich meine Bildschirmfarbeneinstellungen anpassen :)
BatteryBackupUnit
Unterstützt dies die Erweiterung von Großbuchstaben wie .JPG oder .MKV?
Wahyu
1
Der Fehler bei der SelectMany-Lösung besteht darin, dass alle Dateien einmal pro übergebener Dateierweiterung durchlaufen werden.
17 vom 26.
16

Ich weiß, es ist eine alte Frage, aber LINQ: (.NET40 +)

var files = Directory.GetFiles("path_to_files").Where(file => Regex.IsMatch(file, @"^.+\.(wav|mp3|txt)$"));
Eisjäger
quelle
3
Gute Idee. Erwägen Sie die file.ToLower()einfache Verwendung von Erweiterungen in Großbuchstaben. Und warum nicht zuerst die Erweiterung extrahieren, damit Regex nicht den gesamten Pfad untersuchen muss: Regex.IsMatch(Path.GetExtension(file).ToLower(), @"\.(wav|mp3|txt)");
ToolmakerSteve
13

Es gibt auch eine Abstiegslösung, die keinen Speicher- oder Leistungsaufwand zu haben scheint und recht elegant ist:

string[] filters = new[]{"*.jpg", "*.png", "*.gif"};
string[] filePaths = filters.SelectMany(f => Directory.GetFiles(basePath, f)).ToArray();
Bas1l
quelle
1
Ich nehme an, ich könnte es so bearbeiten, dass es eine unbekannte unbegrenzte Anzahl von Erweiterungen mit einer neuen Zeichenfolgenvariablen und einer Split-Funktion akzeptiert. Aber selbst dann, wie ist das besser als die Lösung von jnoreiga? Ist es schneller Weniger Speicherverbrauch?
Klammern
1
Es gibt einen Kompromiss. Dieser Ansatz ruft GetFiles mehrmals auf, einen pro Filter. Diese mehrfachen Aufrufe können in einigen Situationen einen erheblichen "Leistungsaufwand" bedeuten. Dies hat den wichtigen Vorteil, dass jedes GetFiles nur ein Array mit den entsprechenden Dateipfaden zurückgibt . Ich würde erwarten, dass dies normalerweise ein gutes Leistungsergebnis ist, vielleicht sogar eine überlegene Leistung, aber das muss getestet werden. Wenn GetFiles erheblich schneller als EnumerateFiles ist, ist dies möglicherweise der bisher beste Ansatz. Beachten Sie auch, dass das endgültige ".ToArray ()" weggelassen werden kann, wenn IEnumerable direkt verwendet werden kann.
ToolmakerSteve
11

Eine andere Möglichkeit, Linq zu verwenden, ohne jedoch alles zurückgeben und im Speicher filtern zu müssen.

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

Es sind eigentlich 2 Anrufe GetFiles(), aber ich denke, es stimmt mit dem Geist der Frage überein und gibt sie in einer Aufzählung zurück.

Dave Rael
quelle
Warum dann Linq verwenden? Wäre es schneller als die Verwendung einer Liste und eines Adressbereichs?
ThunderGr
1
Ich weiß nicht, was schneller wäre und denke nicht, dass es eine wichtige Frage ist. Für fast jeden Ort, an dem Sie den Code für eine Lösung dieses Problems verwenden würden, wäre der Leistungsunterschied vernachlässigbar. Die Frage sollte sein, was besser lesbar ist, um die Wartbarkeit des Codes in Zukunft zu erleichtern. Ich denke, dies ist eine vernünftige Antwort, weil sie in einer Quellzeile zusammengefasst ist, die meiner Meinung nach Teil dessen ist, was die Frage wünscht, welche Anrufe erforderlich sind und die Absicht dieser Zeile klar zum Ausdruck bringt. list and addrange lenkt mit mehreren Schritten ab, um dasselbe zu erreichen.
Dave Rael
7

Nee. Versuche Folgendes:

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 )
    {
        ...;
    }

Entnommen aus: http://blogs.msdn.com/markda/archive/2006/04/20/580075.aspx

Nicht ich
quelle
7

Lassen

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

Dann

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

oder

from file in Directory.GetFiles(path, "*.*", SearchOption.AllDirectories)
from ext in set
where String.Equals(ext, new FileInfo(file).Extension, StringComparison.OrdinalIgnoreCase)
select file;
abatishchev
quelle
getfiles haben nicht die Überladung, die du gepostet hast.
Nawfal
5

Ich kann nicht verwenden .Where Methode , da ich in .NET Framework 2.0 programmiere (Linq wird nur in .NET Framework 3.5+ unterstützt).

Code ist unten nicht Groß- und Kleinschreibung (so .CaBoder .cabwird auch aufgeführt werden).

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);
    }
}
jaysponsored
quelle
4

Die folgende Funktion sucht nach mehreren Mustern, die durch Kommas getrennt sind. Sie können auch einen Ausschluss angeben, z. B.: "! Web.config" sucht nach allen Dateien und schließt "web.config" aus. Muster können gemischt werden.

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();

}

Verwendungszweck:

foreach (string file in FindFiles(@"D:\628.2.11", @"!*.config, !*.js", SearchOption.AllDirectories))
            {
                Console.WriteLine(file);
            }
Alexander Popov
quelle
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);
}
Rajeesh Kuthuparakkal
quelle
file.Extension.ToLower()ist schlechte Praxis.
Abatishchev
was sollen wir dann verwenden? @abatishchev
Nitin Sawant
@ Nitin:String.Equals(a, b, StringComparison.OrdinalIgnoreCase)
Abatishchev
1
Eigentlich ist file.Extension.Equals (". Jpg", StringComparison.OrdinalIgnoreCase) das, was ich bevorzuge. Es scheint schneller zu sein als .ToLower oder .ToUpper, oder so heißt es überall, wo ich gesucht habe. Tatsächlich ist .Equals auch schneller als ==, da == .Equals aufruft und nach null sucht (da Sie null.Equals (null) nicht ausführen können).
ThunderGr
4

in .NET 2.0 (kein 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()
}

Dann benutze es:

foreach (string fn in GetFilez(path
                             , System.IO.SearchOption.AllDirectories
                             , "*.xml", "*.xml.rels", "*.rels"))
{}
Stefan Steiger
quelle
4
DirectoryInfo directory = new DirectoryInfo(Server.MapPath("~/Contents/"));

//Using Union

FileInfo[] files = directory.GetFiles("*.xlsx")
                            .Union(directory
                            .GetFiles("*.csv"))
                            .ToArray();
Nilesh Padhiyar
quelle
3

Habe gerade einen anderen Weg gefunden, es zu tun. Immer noch nicht eine Operation, aber wirf sie raus, um zu sehen, was andere Leute darüber denken.

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;
}
Jason Z.
quelle
3

Wie wäre es mit

string[] filesPNG = Directory.GetFiles(path, "*.png");
string[] filesJPG = Directory.GetFiles(path, "*.jpg");
string[] filesJPEG = Directory.GetFiles(path, "*.jpeg");

int totalArraySizeAll = filesPNG.Length + filesJPG.Length + filesJPEG.Length;
List<string> filesAll = new List<string>(totalArraySizeAll);
filesAll.AddRange(filesPNG);
filesAll.AddRange(filesJPG);
filesAll.AddRange(filesJPEG);
MattyMerrix
quelle
2

Machen Sie die gewünschten Erweiterungen zu einer Zeichenfolge, dh ".mp3.jpg.wma.wmf", und prüfen Sie dann, ob jede Datei die gewünschte Erweiterung enthält. Dies funktioniert mit .net 2.0, da LINQ nicht verwendet wird.

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

   }
}

Der Vorteil dieses Ansatzes ist, dass Sie Erweiterungen hinzufügen oder entfernen können, ohne den Code zu bearbeiten, dh um PNG-Bilder hinzuzufügen, schreiben Sie einfach myExtensions = ". Jpg.mp3.png".

Evado
quelle
es weiß nicht was ists
Klammern
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();
}
A. Ramazani
quelle
2

Nein ... Ich glaube, Sie müssen so viele Anrufe tätigen, wie Sie möchten.

Ich würde selbst eine Funktion erstellen, die ein Array für Zeichenfolgen mit den von mir benötigten Erweiterungen verwendet und dann auf diesem Array iteriert und alle erforderlichen Aufrufe ausführt. Diese Funktion würde eine allgemeine Liste der Dateien zurückgeben, die den von mir gesendeten Erweiterungen entsprechen.

Ich hoffe es hilft.

Sebagomez
quelle
1

Ich hatte das gleiche Problem und konnte nicht die richtige Lösung finden. Deshalb schrieb ich eine Funktion namens 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();
}

Diese Funktion ruft Directory.Getfiles()nur einmal auf.

Rufen Sie zum Beispiel die Funktion folgendermaßen auf:

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

BEARBEITEN: Um eine Datei mit mehreren Erweiterungen zu erhalten, verwenden Sie diese:

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

Rufen Sie zum Beispiel die Funktion folgendermaßen auf:

string image = GetFile("imagename", new List<string>{"jpg", "png", "gif"}, "imageFolder");
Quispie
quelle
1

Ich frage mich, warum es so viele "Lösungen" gibt?

Wenn mein Anfängerverständnis darüber, wie GetFiles funktioniert, richtig ist, gibt es nur zwei Optionen, und jede der oben genannten Lösungen kann auf diese zurückgeführt werden:

  1. GetFiles, dann Filter: Schnell, aber ein Speicherkiller aufgrund des Speicheraufwands, bis die Filter angewendet werden

  2. Filtern während GetFiles: Langsamer, je mehr Filter eingestellt sind, aber geringer Speicherbedarf, da kein Overhead gespeichert wird.
    Dies wird in einem der oben genannten Beiträge mit einem beeindruckenden Benchmark erläutert: Jede Filteroption bewirkt eine separate GetFile-Operation, sodass derselbe Teil der Festplatte mehrmals gelesen wird.

Meiner Meinung nach ist Option 1) besser, aber die Verwendung von SearchOption.AllDirectories in Ordnern wie C: \ würde sehr viel Speicher verbrauchen.
Daher würde ich nur eine rekursive Untermethode erstellen, die mit Option 1) alle Unterordner durchläuft.

Dies sollte nur 1 GetFiles-Operation für jeden Ordner verursachen und daher schnell sein (Option 1), aber nur wenig Speicher verwenden, da die Filter nach dem Lesen jedes Unterordners angewendet werden -> Overhead wird nach jedem Unterordner gelöscht.

Bitte korrigieren Sie mich, wenn ich falsch liege. Ich bin, wie gesagt, ziemlich neu in der Programmierung, möchte aber ein tieferes Verständnis der Dinge erlangen, um irgendwann gut darin zu werden :)

Janis
quelle
1

Wenn Sie VB.NET verwenden (oder die Abhängigkeit in Ihr C # -Projekt importieren), gibt es tatsächlich eine praktische Methode, mit der Sie nach mehreren Erweiterungen filtern können:

Microsoft.VisualBasic.FileIO.FileSystem.GetFiles("C:\\path", Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, new string[] {"*.mp3", "*.jpg"});

In VB.NET kann über den My-Namespace darauf zugegriffen werden:

My.Computer.FileSystem.GetFiles("C:\path", FileIO.SearchOption.SearchAllSubDirectories, {"*.mp3", "*.jpg"})

Leider unterstützen diese Convenience-Methoden keine träge bewertete Variante wie Directory.EnumerateFiles()diese.

Crusha K. Rool
quelle
Dies ist mit Sicherheit die beste Antwort, und dennoch wird etwas viel Hackigeres akzeptiert. Muss ich so lieben.
Robbie Coyne
0

Ich weiß nicht, welche Lösung besser ist, aber ich benutze diese:

String[] ext = "*.ext1|*.ext2".Split('|');

            List<String> files = new List<String>();
            foreach (String tmp in ext)
            {
                files.AddRange(Directory.GetFiles(dir, tmp, SearchOption.AllDirectories));
            }
elle0087
quelle
0

Hier finden Sie eine einfache und elegante Möglichkeit, gefilterte Dateien abzurufen

var allowedFileExtensions = ".csv,.txt";


var files = Directory.EnumerateFiles(@"C:\MyFolder", "*.*", SearchOption.TopDirectoryOnly)
                .Where(s => allowedFileExtensions.IndexOf(Path.GetExtension(s)) > -1).ToArray(); 
JohnnBlade
quelle
-1

Oder Sie können einfach die Zeichenfolge der Erweiterungen in Zeichenfolge ^ konvertieren

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;
}
user3512661
quelle
2
Dies ist c ++ nicht c #
Klammern
-1

Die Verwendung des GetFiles-Suchmusters zum Filtern der Erweiterung ist nicht sicher !! Zum Beispiel haben Sie zwei Dateien Test1.xls und Test2.xlsx und möchten die xls-Datei mithilfe des Suchmusters * .xls herausfiltern, aber GetFiles gibt sowohl Test1.xls als auch Test2.xlsx zurück. Ich war mir dessen nicht bewusst und habe einen Fehler in der Produktion erhalten Umgebung, in der einige temporäre Dateien plötzlich als richtige Dateien behandelt wurden. Das Suchmuster war * .txt und die temporären Dateien wurden * .txt20181028_100753898 benannt. Damit das Suchmuster nicht vertrauenswürdig ist, müssen Sie auch die Dateinamen zusätzlich überprüfen.

WillyS
quelle
Beantwortet die Frage nicht.
Robbie Coyne