Можете ли вы вызвать Directory.GetFiles () с несколькими фильтрами? - PullRequest
320 голосов
/ 02 октября 2008

Я пытаюсь использовать метод Directory.GetFiles() для получения списка файлов нескольких типов, таких как mp3 и jpg. Я попробовал оба из следующих безуспешно:

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

Есть ли способ сделать это за один звонок?

Ответы [ 26 ]

4 голосов
/ 18 сентября 2010
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);
}
4 голосов
/ 31 мая 2010

Следующая функция выполняет поиск по нескольким шаблонам, разделенным запятыми. Вы также можете указать исключение, например: «! Web.config» будет искать все файлы и исключать «web.config». Шаблоны могут быть смешаны.

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

}

Использование:

foreach (string file in FindFiles(@"D:\628.2.11", @"!*.config, !*.js", SearchOption.AllDirectories))
            {
                Console.WriteLine(file);
            }
3 голосов
/ 19 апреля 2013
DirectoryInfo directory = new DirectoryInfo(Server.MapPath("~/Contents/"));

//Using Union

FileInfo[] files = directory.GetFiles("*.xlsx")
                            .Union(directory
                            .GetFiles("*.csv"))
                            .ToArray();
3 голосов
/ 02 октября 2008

Просто нашел другой способ сделать это. Все еще не одна операция, но выбрасывание, чтобы посмотреть, что другие люди думают об этом.

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;
}
3 голосов
/ 21 мая 2015

А как же

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);
2 голосов
/ 03 сентября 2014

в .NET 2.0 (без 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()
}

Тогда используйте это:

foreach (string fn in GetFilez(path
                             , System.IO.SearchOption.AllDirectories
                             , "*.xml", "*.xml.rels", "*.rels"))
{}
2 голосов
/ 15 декабря 2011
/// <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();
}
2 голосов
/ 03 апреля 2012

Создайте нужные вам расширения в одну строку, т.е. ".mp3.jpg.wma.wmf", а затем проверьте, содержит ли каждый файл нужное вам расширение. Это работает с .net 2.0, поскольку он не использует 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

   }
}

Преимущество этого подхода в том, что вы можете добавлять или удалять расширения без редактирования кода, т. Е. Для добавления изображений PNG, просто напишите myExtensions = ". Jpg.mp3.png".

2 голосов
/ 02 октября 2008

Нет ... Я считаю, что вам нужно сделать столько звонков, сколько вам нужно.

Я бы сам создал функцию, получающую массив из строк с нужными мне расширениями, а затем выполнял бы итерацию по этому массиву, делая все необходимые вызовы. Эта функция возвращает общий список файлов, соответствующих отправленным мною расширениям.

Надеюсь, это поможет.

1 голос
/ 02 апреля 2013

Интересно, почему опубликовано так много «решений»?

Если мое понимание новичка о том, как работает GetFiles, верно, есть только два варианта, и любое из приведенных выше решений может быть сведено к следующему:

  1. GetFiles, затем фильтр: быстро, но убийца памяти из-за сохранения служебной информации до применения фильтров

  2. Фильтр в то время как GetFiles: чем медленнее установлено больше фильтров, но тем не менее не используется объем памяти, поскольку не сохраняется служебная информация.
    Это объясняется в одном из приведенных выше постов с впечатляющим тестом: каждый параметр фильтра вызывает отдельную операцию GetFile, поэтому одна и та же часть жесткого диска читается несколько раз.

На мой взгляд, вариант 1) лучше, но использование директорий SearchOption.AllDirector для таких папок, как C: \, потребовало бы огромных объемов памяти.
Поэтому я бы просто сделал рекурсивный под-метод, который просматривает все подпапки, используя опцию 1)

Это должно вызывать только 1 операцию GetFiles для каждой папки и, следовательно, быть быстрым (Вариант 1), но использовать только небольшой объем памяти, так как фильтры применяются после чтения каждой подпапки -> издержки удаляются после каждой подпапки.

Пожалуйста, поправьте меня, если я ошибаюсь. Я, как я уже сказал, довольно плохо знаком с программированием, но хочу получить более глубокое понимание вещей, чтобы в конечном итоге стать хорошим в этом:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...