Czy możesz wywołać Directory.GetFiles () z wieloma filtrami?

353

Próbuję użyć tej Directory.GetFiles()metody do pobrania listy plików wielu typów, takich jak mp3„s jpg” i „s”. Próbowałem obu z poniższych bez powodzenia:

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

Czy można to zrobić za jednym razem?

Jason Z
źródło
3
Na marginesie, użycie wzorca wyszukiwania GetFiles do filtrowania rozszerzenia nie jest bezpieczne. Na przykład masz dwa pliki Test1.xls i Test2.xlsx i chcesz odfiltrować plik xls przy użyciu wzorca wyszukiwania * .xls, ale GetFiles zwraca oba Test1 .xls i Test2.xlsx. Przeczytaj sekcję notatek, aby uzyskać więcej informacji
Kiran
Jak więc temu zapobiec?
Wsporniki
2
@kiran Jak to nie jest bezpieczne? To wygląda raczej na funkcję niż na błąd.
Kyle Delaney,

Odpowiedzi:

519

W przypadku .NET 4.0 i nowszych wersji

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

W przypadku wcześniejszych wersji .NET

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

edycja: Proszę przeczytać komentarze. Poprawa, którą sugeruje Paul Farry , oraz problem pamięci / wydajności, na który wskazuje Christian.K , są bardzo ważne.

Christoffer Lette
źródło
10
Człowieku, muszę częściej myśleć w kategoriach LINQ. Fajne rozwiązanie!
Ken Pespisa,
61
Upewnij się jednak, że rozumiesz implikacje: spowoduje to zwrócenie wszystkich plików w tablicy ciągów, a następnie odfiltrowanie ich według określonych rozszerzeń. To może nie być duży problem, jeśli „C: \ Path” nie ma pod nim wielu plików, ale może to być problem z pamięcią / wydajnością w „C: \” lub coś w tym rodzaju.
Christian.K
24
... 2 lata później: fajny kod, ale uważaj na to, jeśli masz plik z rozszerzeniem .JPG, nie da rady. Lepiej dodajs.ToLower().Endswith...
Stormenet,
107
możesz po prostu użyćs.EndsWith(".mp3", StringComparison.OrdinalIgnoreCase)
Paul Farry
119
Należy zauważyć, że z .NET 4.0, można wymienić Directory.GetFilesz Directory.EnumerateFiles, msdn.microsoft.com/en-us/library/dd383571.aspx , co pozwoli uniknąć problemów z pamięcią, że @ Christian.K wspomina.
Jim Mischel,
60

Co powiesz na to:

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

Znalazłem to tutaj (w komentarzach): http://msdn.microsoft.com/en-us/library/wz42302f.aspx

Albert
źródło
Zgaduję, że to pozwala uniknąć potencjalnych pułapek pamięciowych najlepiej ocenianej odpowiedzi? W takim przypadku powinien zostać oceniony wyżej!
Dan W
11
@DanW Najwyżej oceniana odpowiedź z pewnością obciąża pamięć, ale myślę, że nie powinien to być taki problem. Podobała mi się również ta odpowiedź, ale jest ona (znacznie) wolniejsza niż odpowiedź zaakceptowana. Sprawdź ten SpeedTest
OttO
Dzięki. Cieszę się, że jest tylko dwa razy wolniejszy - myślę, że będę go trzymać w międzyczasie.
Dan W
7
Jest tylko dwa razy wolniejszy, jeśli istnieją tylko dwa rozszerzenia. Jeśli masz listę rozszerzeń X, będzie ona X razy wolniejsza. Ponieważ tutaj wywołujesz funkcję Directory.GetFiles kilka razy, podczas gdy w drugim rozwiązaniu jest ona wywoływana tylko raz.
Oscar Hermosilla
1
@OscarHermosilla Można użyć, Parallel.ForEachaby uzyskać je równolegle
FindOutIslamNow
33

Jeśli masz dużą listę rozszerzeń do sprawdzenia, możesz użyć następujących. Nie chciałem tworzyć wielu instrukcji OR, więc zmodyfikowałem to, co napisał 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
}
jnoreiga
źródło
Pomóż mi z tym, proszę ... Kiedy drukuję imageFile, podaje pełną ścieżkę. Jak mogę go zmniejszyć do samej nazwy pliku.
Naresh
1
System.IO.Path.GetFileName (
imageFile
Path.GetExtensionzwraca „.ext”, a nie „* .ext” (przynajmniej w wersji 3.5+).
nullable
2
FYI: Potrzebujesz System.Linq dla .where (
jnoreiga
1
Istnieje potencjalna wada. Już dawno minęły czasy, kiedy rozszerzenia muszą mieć dokładnie trzy znaki. Załóżmy, że możesz napotkać plik .abc, a obsługiwane rozszerzenie zawiera .abcd. Będzie pasować, choć nie powinno. Aby naprawić: za supportedExtensions = ".jpg|.abcd|";pomocą .Contains(Path.GetExtension(s).ToLower() + "|"). Oznacza to, że w teście umieść znak separatora. WAŻNE: znak separatora musi także znajdować się po POSTANOWIU w obsługiwanych wyjątkach.
ToolmakerSteve,
31

dla

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

Mógłbyś:

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

Ale prawdziwa korzyść EnumerateFilespojawia się po podzieleniu filtrów i scaleniu wyników:

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

Robi się trochę szybciej, jeśli nie musisz zamieniać ich w globusy (tj. exts = new[] {"*.mp3", "*.jpg"}Już).

Ocena wydajności na podstawie następującego testu LinqPad (uwaga: Perfwystarczy powtórzyć delegata 10000 razy) https://gist.github.com/zaus/7454021

(przesłany i rozszerzony z „duplikatu”, ponieważ to pytanie wyraźnie nie wymagało LINQ: Wiele rozszerzeń plików searchPattern dla System.IO.Directory.GetFiles )

drzaus
źródło
co rozumiesz przez „jestem trochę szybszy, jeśli nie musisz zamieniać ich w globusy”? Czy to O (1) czy O (n) (pod względem liczby plików, a nie liczby rozszerzeń)? Domyślam się, że to O (1) (lub O (n) w odniesieniu do liczby rozszerzeń) i prawdopodobnie gdzieś w zakresie kilku cykli procesora ... W takim przypadku jest to prawdopodobnie - pod względem wydajności - nieistotne
BatteryBackupUnit
@BatteryBackupUnit tak, przy 10 000 powtórzeń dla 2 rozszerzeń różnica glob vs. str wynosi 3 ms, więc tak technicznie nieistotna (patrz link wyników), ale nie wiedząc, ile rozszerzeń trzeba filtrować, pomyślałem, że warto wskazać, że istnieje różnica; pozostawiam wam decyzję, czy „uproszczone użycie” (tj. .FilterFiles(path, "jpg", "gif")) jest lepsze niż „jawne globusy” (tj .FilterFiles(path, "*.jpg", "*.gif").).
drzaus
perfekcyjnie, dzięki. Przepraszam, ale jakoś pominąłem ten link github. Może powinienem dostosować ustawienia kolorów ekranu :)
BatteryBackupUnit
Czy to obsługuje rozszerzenie wielkich liter, takie jak .JPG lub .MKV?
Wahyu,
1
Wadą rozwiązania SelectMany jest to, że będzie iterował wszystkie pliki jeden raz na każde przekazane rozszerzenie pliku.
17 z 26
16

Wiem, że to stare pytanie, ale LINQ: (.NET40 +)

var files = Directory.GetFiles("path_to_files").Where(file => Regex.IsMatch(file, @"^.+\.(wav|mp3|txt)$"));
Icehunter
źródło
3
Dobry pomysł. Rozważ użycie file.ToLower()łatwego dopasowania do wielkich liter. A może najpierw wyodrębnisz rozszerzenie, aby Regex nie musiał sprawdzać całej ścieżki: Regex.IsMatch(Path.GetExtension(file).ToLower(), @"\.(wav|mp3|txt)");
ToolmakerSteve
13

Istnieje również rozwiązanie opadania, które wydaje się nie mieć narzutu pamięci ani wydajności i jest dość eleganckie:

string[] filters = new[]{"*.jpg", "*.png", "*.gif"};
string[] filePaths = filters.SelectMany(f => Directory.GetFiles(basePath, f)).ToArray();
Bas1l
źródło
1
Przypuszczam, że mógłbym go edytować, aby akceptował nieznaną nieograniczoną liczbę rozszerzeń z nową zmienną łańcuchową i funkcją Split. Ale nawet wtedy, jak to jest lepsze niż rozwiązanie jnoreiga? Czy to jest szybsze? Mniejsze zużycie pamięci?
Wsporniki
1
Występuje kompromis. Takie podejście wywołuje GetFiles wiele razy, po jednym na filtr. Te wielokrotne wywołania mogą być znaczącym „narzutem wydajności” w niektórych sytuacjach. Ma tę ważną zaletę, że każde GetFiles zwraca tylko tablicę z pasującymi ścieżkami plików. Spodziewałbym się, że będzie to zwykle dobry wynik wydajności, może nawet lepsza wydajność, ale to należy przetestować. Jeśli GetFiles jest znacznie szybszy niż EnumerateFiles, może to być najlepsze jak dotąd podejście. Zauważ również, że końcowy „.ToArray ()” można pominąć, gdy IEnumerable jest bezpośrednio użyteczny.
ToolmakerSteve
11

Kolejny sposób korzystania z Linq, ale bez konieczności zwracania wszystkiego i filtrowania tego w pamięci.

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

W rzeczywistości są to 2 wezwania do GetFiles(), ale myślę, że jest to zgodne z duchem pytania i zwraca je w jednym wyliczeniu.

Dave Rael
źródło
Dlaczego więc korzystać z Linq? Czy byłoby to szybsze niż używanie listy i addrange?
ThunderGr
1
nie wiem, co byłoby szybsze i nie sądzę, że to ważne pytanie. w prawie każdym miejscu, w którym użyjesz kodu do rozwiązania tego problemu, różnica w wydajności byłaby znikoma. pytanie powinno dotyczyć tego, co jest bardziej czytelne, aby ułatwić utrzymanie kodu w przyszłości. myślę, że jest to rozsądna odpowiedź, ponieważ umieszcza się w jednej linii źródłowej, która, jak sądzę, jest częścią tego, czego pragnie pytanie, niezbędne połączenia i wyraźnie wyraża intencję tej linii. lista i addrange rozpraszają uwagę wieloma krokami, aby osiągnąć to samo.
Dave Rael
7

Nie. Spróbuj wykonać następujące czynności:

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

Pobrano z: http://blogs.msdn.com/markda/archive/2006/04/20/580075.aspx

Nie ja
źródło
7

Pozwolić

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

Następnie

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

lub

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
źródło
w getfiles nie ma opublikowanego przeciążenia.
nawfal
5

Nie mogę użyć .Wheremetody, ponieważ programuję w .NET Framework 2.0 (Linq jest obsługiwany tylko w .NET Framework 3.5+).

Poniższy kod nie rozróżnia wielkości liter (tak .CaBlub też .cabbędzie wymieniony).

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);
    }
}
jaysponsorowane
źródło
4

Poniższa funkcja wyszukuje wiele wzorów oddzielonych przecinkami. Możesz także określić wykluczenie, np .: „! Web.config” wyszuka wszystkie pliki i wykluczy „web.config”. Wzory można mieszać.

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

}

Stosowanie:

foreach (string file in FindFiles(@"D:\628.2.11", @"!*.config, !*.js", SearchOption.AllDirectories))
            {
                Console.WriteLine(file);
            }
Alexander Popov
źródło
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
źródło
file.Extension.ToLower()jest złą praktyką.
abatishchev
więc czego powinniśmy użyć? @abatishchev
Nitin Sawant
@Nitin:String.Equals(a, b, StringComparison.OrdinalIgnoreCase)
abatishchev
1
W rzeczywistości wolę file.Extension.Equals (". Jpg", StringComparison.OrdinalIgnoreCase). Wydaje się być szybszy niż .ToLower lub .ToUpper, a przynajmniej tak mówią, wszędzie tam, gdzie szukałem. W rzeczywistości .Equals jest również szybszy niż ==, ponieważ == wywołuje .Equals i sprawdza, czy null (Ponieważ nie można zrobić null.Equals (null)).
ThunderGr
4

w .NET 2.0 (bez 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()
}

Następnie użyj go:

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

//Using Union

FileInfo[] files = directory.GetFiles("*.xlsx")
                            .Union(directory
                            .GetFiles("*.csv"))
                            .ToArray();
Nilesh Padhiyar
źródło
3

Właśnie znalazłem inny sposób, aby to zrobić. Nadal nie jedna operacja, ale wyrzucenie jej, aby zobaczyć, co myślą o niej inni ludzie.

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
źródło
3

Co powiesz na

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
źródło
2

Utwórz rozszerzenia, które mają mieć jeden ciąg, tj. „.Mp3.jpg.wma.wmf”, a następnie sprawdź, czy każdy plik zawiera odpowiednie rozszerzenie. Działa to z .net 2.0, ponieważ nie używa LINQ.

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

   }
}

Zaletą tego podejścia jest to, że możesz dodawać lub usuwać rozszerzenia bez edycji kodu, tj. Aby dodać obrazy png, po prostu napisz myExtensions = ". Jpg.mp3.png".

Evado
źródło
nie wie co to jests
Wsporniki
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
źródło
2

Nie ... Uważam, że musisz wykonać tyle połączeń, ile chcesz typów plików.

Sam stworzyłbym funkcję, biorąc tablicę na ciągi znaków z potrzebnymi rozszerzeniami, a następnie iterowałem tę tablicę, wykonując wszystkie niezbędne wywołania. Ta funkcja zwróci ogólną listę plików pasujących do rozszerzeń, które wysłałem.

Mam nadzieję, że to pomoże.

sebagomez
źródło
1

Miałem ten sam problem i nie mogłem znaleźć właściwego rozwiązania, więc napisałem funkcję o nazwie 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();
}

Ta funkcja zadzwoni Directory.Getfiles()tylko raz.

Na przykład wywołaj taką funkcję:

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

EDYCJA: Aby uzyskać jeden plik z wieloma rozszerzeniami, użyj tego:

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

Na przykład wywołaj taką funkcję:

string image = GetFile("imagename", new List<string>{"jpg", "png", "gif"}, "imageFolder");
Quispie
źródło
1

Zastanawiam się, dlaczego opublikowano tak wiele „rozwiązań”?

Jeśli moje zrozumienie dla początkujących, jak działa GetFiles, jest słuszne, istnieją tylko dwie opcje i każde z powyższych rozwiązań można sprowadzić do następujących:

  1. GetFiles, a następnie filtruj: Szybko, ale zabójca pamięci z powodu przechowywania narzutu do momentu zastosowania filtrów

  2. Filtruj podczas GetFiles: Im wolniej, tym więcej filtrów jest ustawionych, ale niskie zużycie pamięci, ponieważ nie jest przechowywany żaden narzut.
    Jest to wyjaśnione w jednym z powyższych postów z imponującym testem porównawczym: Każda opcja filtru powoduje oddzielną operację GetFile, dzięki czemu ta sama część dysku twardego jest czytana kilka razy.

Moim zdaniem opcja 1) jest lepsza, ale użycie SearchOption.AllDirectories w folderach takich jak C: \ zużyłoby ogromne ilości pamięci.
Dlatego właśnie stworzyłbym rekursywną pod-metodę, która przechodzi przez wszystkie podfoldery przy użyciu opcji 1)

Powinno to spowodować tylko 1 operację GetFiles na każdym folderze i dlatego powinno być szybkie (Opcja 1), ale zużywać tylko niewielką ilość pamięci, ponieważ filtry są stosowane po odczytaniu każdego podfoldera -> obciążenie jest usuwane po każdym podfolderze.

Proszę, popraw mnie jeśli się mylę. Jestem, jak powiedziałem, całkiem nowy w programowaniu, ale chcę uzyskać głębsze zrozumienie rzeczy, aby ostatecznie stać się w tym dobry :)

Janis
źródło
1

Jeśli używasz VB.NET (lub zaimportowałeś zależność do swojego projektu w C #), faktycznie istnieje metoda wygody, która pozwala na filtrowanie wielu rozszerzeń:

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

W VB.NET można uzyskać do niego dostęp poprzez przestrzeń nazw My:

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

Niestety te metody wygody nie obsługują leniwie ocenianego wariantu Directory.EnumerateFiles().

Crusha K. Rool
źródło
To jest z pewnością najlepsza odpowiedź, a jednak coś znacznie bardziej hackerskiego to zaakceptowana. Kocham SO.
Robbie Coyne,
0

nie wiem, które rozwiązanie jest lepsze, ale używam tego:

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
źródło
0

Oto prosty i elegancki sposób na uzyskanie odfiltrowanych plików

var allowedFileExtensions = ".csv,.txt";


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

Lub możesz po prostu przekonwertować ciąg rozszerzeń na Ciąg ^

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;
}
użytkownik3512661
źródło
2
To jest c ++, a nie c #
Wsporniki
-1

Używanie wzorca wyszukiwania GetFiles do filtrowania rozszerzenia nie jest bezpieczne !! Na przykład masz dwa pliki Test1.xls i Test2.xlsx i chcesz odfiltrować plik xls za pomocą wzorca wyszukiwania * .xls, ale GetFiles zwraca oba Test1.xls i Test2.xlsx Nie wiedziałem o tym i wystąpił błąd w produkcji środowisko, gdy niektóre pliki tymczasowe nagle zostały potraktowane jako odpowiednie pliki. Wzorzec wyszukiwania to * .txt, a pliki tymczasowe nazwano * .txt20181028_100753898 Aby wzorzec wyszukiwania nie mógł być zaufany, należy dodatkowo sprawdzić nazwy plików.

WillyS
źródło
Nie odpowiada na pytanie.
Robbie Coyne