Я пытаюсь использовать метод Directory.GetFiles() для получения списка файлов нескольких типов, таких как mp3 и jpg. Я безуспешно пробовал оба следующих варианта:
Directory.GetFiles("C:\path", "*.mp3|*.jpg", SearchOption.AllDirectories);
Directory.GetFiles("C:\path", "*.mp3;*.jpg", SearchOption.AllDirectories);
Есть ли способ сделать это за один звонок?
Так как этого избежать?
@kiran Как это не безопасно? Это похоже на функцию, а не на ошибку.
Так как этого избежать? Использование? .Xls будет правильно фильтровать только файлы xls и, например, не будет включать файлы xlsx.





Неа. Попробуйте следующее:
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 )
{
...;
}
Взято из: http://blogs.msdn.com/markda/archive/2006/04/20/580075.aspx
Нет ... Я считаю, что вам нужно делать столько звонков, сколько типов файлов вы хотите.
Я бы сам создал функцию, взяв массив строк с нужными мне расширениями, а затем перебрал бы этот массив, сделав все необходимые вызовы. Эта функция вернет общий список файлов, соответствующих отправленным мной расширениям.
Надеюсь, это поможет.
Для .NET 4.0 и более поздних версий
var files = Directory.EnumerateFiles("C:\path", "*.*", SearchOption.AllDirectories)
.Where(s => s.EndsWith(".mp3") || s.EndsWith(".jpg"));
Для более ранних версий .NET
var files = Directory.GetFiles("C:\path", "*.*", SearchOption.AllDirectories)
.Where(s => s.EndsWith(".mp3") || s.EndsWith(".jpg"));
редактировать:Пожалуйста, прочтите комментарии. Улучшение, которое предлагает Пол Фарри, и проблема памяти / производительности, на которую указывает Christian.K, очень важны.
Чувак, мне нужно чаще думать в терминах LINQ. Хорошее решение!
Просто убедитесь, что вы понимаете последствия: это вернет файлы все в массиве строк, а затем отфильтрует их по указанным вами расширениям. Это может не быть большой проблемой, если под «C: \ Path» нет большого количества файлов, но может быть проблема с памятью / производительностью на «C: \» или что-то в этом роде.
... 2 года спустя: Хороший код, но будьте осторожны, если у вас есть файл с расширением .JPG, он его не сделает. Лучше добавить s.ToLower().Endswith...
вы можете просто использовать s.EndsWith(".mp3", StringComparison.OrdinalIgnoreCase)
Чтобы сократить условия или, мне нравится делать следующее (хотя я не уверен, что это влияет на производительность больше) ... var files = myDirInfo.GetFiles (). Where (o => new [] { "mp3", "jpg"}. Содержит (o.Extension.ToLower ()). ToArray ();
Обратите внимание, что с .NET 4.0 вы можете заменить Directory.GetFiles на Directory.EnumerateFiles, msdn.microsoft.com/en-us/library/dd383571.aspx, что позволит избежать проблем с памятью, о которых упоминает @ Christian.K.
@MattWinward вы должны прочитать msdn.microsoft.com/en-us/library/dd465121.aspx
Я сделал некоторые улучшения производительности и предоставил сравнительный код в ответе ниже: stackoverflow.com/questions/163162/…
@MAC Это параметр лямбда-выражения, в данном случае s представляет каждое имя файла, возвращаемое в результате вызова Directory.EnumerateFiles / Directory.GetFiles.
У вас есть решение для .Net 2, пожалуйста?
Как проверить, содержит ли имя файла (а не его каталог) конкретную строку?
Если вы хотите еще больше повысить производительность в случае множества возможных расширений, лучше создать HashSet со всеми расширениями и сделать Where(f => _validExtensions.Contains(Path.GetExtension(f).ToLower())). По сути, Contains намного быстрее, чем многократное сравнение строк.
GetFiles намного быстрее, чем EnumerateFiles
В контексте данных вам сначала нужны все файлы, а затем вы их фильтруете.
@IlyaChernomordik: Проблема с .Contains в том, что он включает файлы без расширения.
Обратите внимание, что вы не всегда можете использовать EnumerateFiles, а не GetFiles; например, если вы хотите обрабатывать файлы в определенном порядке, вы хотите, чтобы весь файл был установлен для определения этого порядка перед началом обработки.
Просто нашел другой способ сделать это. По-прежнему не одна операция, а выбросить ее, чтобы узнать, что думают об этом другие.
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;
}
Следующая функция выполняет поиск по нескольким шаблонам, разделенным запятыми. Вы также можете указать исключение, например: «! 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:8.2.11", @"!*.config, !*.js", SearchOption.AllDirectories))
{
Console.WriteLine(file);
}
Позволять
var set = new HashSet<string> { ".mp3", ".jpg" };
Затем
Directory.GetFiles(path, "*.*", SearchOption.AllDirectories)
.Where(f => set.Contains(
new FileInfo(f).Extension,
StringComparer.OrdinalIgnoreCase));
или же
from file in Directory.GetFiles(path, "*.*", SearchOption.AllDirectories)
from ext in set
where String.Equals(ext, new FileInfo(file).Extension, StringComparison.OrdinalIgnoreCase)
select file;
У getfiles нет перегрузки u.
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);
}
file.Extension.ToLower() - плохая практика.
тогда что мы должны использовать? @abatishchev
@ Нитин: String.Equals(a, b, StringComparison.OrdinalIgnoreCase)
На самом деле, я предпочитаю file.Extension.Equals (". Jpg", StringComparison.OrdinalIgnoreC ase). Вроде бы быстрее, чем .ToLower или .ToUpper, по крайней мере так говорят везде, где я искал. На самом деле .Equals также быстрее, чем ==, поскольку == вызывает .Equals и проверяет наличие null (потому что вы не можете делать null.Equals (null)).
Если у вас есть большой список расширений, которые нужно проверить, вы можете использовать следующее. Я не хотел создавать много операторов ИЛИ, поэтому я изменил то, что написал 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
}
Помогите мне с этим, пожалуйста ... Когда я печатаю imageFile, он дает полный путь к нему. Как я могу сжать его до имени файла.
System.IO.Path.GetFileName (файл изображения)
Path.GetExtension возвращает ".ext", а не "* .ext" (по крайней мере, в 3.5+).
К вашему сведению: вам нужен System.Linq для .where (
Зачем использовать запятую в качестве разделительного символа? Запрещенный персонаж, такой как | было бы надежнее. Вы бы исключили (редкий) случай, когда расширение содержит запятую в конце.
Есть потенциальный недостаток. Мы давно прошли те времена, когда требуется, чтобы расширения состояли ровно из трех символов. Предположим, вы можете встретить файл с .abc, а supportedExtensions содержит .abcd. Будет совпадать, хотя и не должно. Чтобы исправить: supportedExtensions = ".jpg|.abcd|"; с .Contains(Path.GetExtension(s).ToLower() + "|"). То есть включите в тест свой символ-разделитель. ВАЖНО: ваш символ-разделитель также должен стоять после ПОСЛЕДНЕЙ записи в supportedExceptions.
Другой недостаток состоит в том, что все решения .Contains включают файлы без расширения.
Я не могу использовать метод .Where, потому что я программирую в .NET Framework 2.0 (Linq поддерживается только в .NET Framework 3.5+).
Приведенный ниже код не чувствителен к регистру (поэтому .CaB или .cab также будут указаны).
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);
}
}
Другой способ использовать Linq, но без необходимости возвращать все и фильтровать это в памяти.
var files = Directory.GetFiles("C:\path", "*.mp3", SearchOption.AllDirectories).Union(Directory.GetFiles("C:\path", "*.jpg", SearchOption.AllDirectories));
На самом деле это 2 вызова GetFiles(), но я думаю, что это соответствует духу вопроса и возвращает их одним перечислимым.
Тогда зачем использовать Linq? Будет ли это быстрее, чем использование списка и добавления диапазона?
Я не знаю, что было бы быстрее, и не думаю, что это важный вопрос. практически для любого места, где вы будете использовать код для любого решения этой проблемы, разница в производительности будет незначительной. вопрос должен заключаться в том, что более читабельно, чтобы облегчить сопровождение кода в будущем. Я думаю, что это разумный ответ, потому что он помещается в одну исходную строку, которая, как мне кажется, является частью того, чего желает вопрос, необходимыми вызовами и четко выражает намерение этой строки. list и addrange отвлекают от множества шагов для достижения одного и того же.
Как насчет этого:
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();
}
Нашел здесь (в комментариях): http://msdn.microsoft.com/en-us/library/wz42302f.aspx
Я предполагаю, что это позволяет избежать потенциальных ошибок памяти, связанных с ответом с самым высоким рейтингом? В таком случае он должен быть оценен выше!
@DanW Самый популярный ответ, безусловно, ложится бременем на память, но я думаю, что это не должно быть такой проблемой. Мне тоже понравился этот ответ, но на самом деле он (намного) медленнее, чем принятый ответ. Отметьте это SpeedTest
Спасибо. Приятно видеть, что он всего в два раза медленнее - пока, думаю, я буду придерживаться его.
Это всего лишь вдвое медленнее, если есть только два расширения. Если у вас есть список X расширений, он будет в X раз медленнее. Потому что здесь вы вызываете функцию Directory.GetFiles несколько раз, тогда как в другом решении она вызывается только один раз.
@OscarHermosilla Можно использовать Parallel.ForEach, чтобы получить их параллельно
@FindOutIslamNow, но тогда вы ограничены пропускной способностью ввода-вывода
@OttO плохая ссылка.
/// <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();
}
Сделайте нужные расширения одной строкой, например ".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".
он не знает, что такое s
Я знаю, что это старый вопрос, но LINQ: (.NET40 +)
var files = Directory.GetFiles("path_to_files").Where(file => Regex.IsMatch(file, @"^.+\.(wav|mp3|txt)$"));
Хорошая идея. Рассмотрите возможность использования file.ToLower() для упрощения сопоставления расширений в верхнем регистре. И почему бы не извлечь сначала расширение, чтобы Regex не проверял весь путь: Regex.IsMatch(Path.GetExtension(file).ToLower(), @"\.(wav|mp3|txt)");
У меня была такая же проблема, и я не мог найти правильного решения, поэтому я написал функцию 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();
}
Эта функция вызовет Directory.Getfiles() только один раз.
Например, вызовите функцию следующим образом:
string[] images = GetFiles(new List<string>{"jpg", "png", "gif"}, "imageFolder");
Обновлено: Чтобы получить один файл с несколькими расширениями, используйте это:
/// <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 "";
}
Например, вызовите функцию следующим образом:
string image = GetFile("imagename", new List<string>{"jpg", "png", "gif"}, "imageFolder");
Существует также решение для спуска, которое, похоже, не имеет накладных расходов на память или производительность и довольно элегантно:
string[] filters = new[]{"*.jpg", "*.png", "*.gif"};
string[] filePaths = filters.SelectMany(f => Directory.GetFiles(basePath, f)).ToArray();
Полагаю, я мог бы отредактировать его, чтобы он принимал неизвестное неограниченное количество расширений с новой строковой переменной и функцией разделения. Но даже тогда, чем это лучше, чем решение jnoreiga? Это быстрее? Меньше потребления памяти?
Есть компромисс. Этот подход вызывает GetFiles несколько раз, по одному на фильтр. Эти множественные вызовы мощь в некоторых ситуациях являются значительными «накладными расходами на производительность». У него есть важное преимущество, заключающееся в том, что каждый GetFiles возвращает только массив с путями к файлам соответствие. Я ожидал, что это как правило будет хорошим результатом по производительности, возможно, даже с производительностью начальство, но это необходимо проверить. Если GetFiles значительно быстрее, чем EnumerateFiles, тогда это может быть лучшим подходом. Также обратите внимание, что последний ".ToArray ()" можно опустить, если IEnumerable можно использовать напрямую.
Интересно, почему опубликовано так много "решений"?
Если мои новички в понимании того, как работает GetFiles, верны, есть только два варианта, и любое из вышеперечисленных решений можно свести к следующему:
GetFiles, затем фильтр: быстро, но убивает память из-за накладных расходов на хранение до применения фильтров
Фильтр во время GetFiles: чем больше фильтров установлено, тем медленнее используется память, так как накладные расходы не сохраняются.
Это объясняется в одном из вышеупомянутых сообщений с впечатляющим тестом: каждая опция фильтра вызывает отдельную операцию GetFile, поэтому одна и та же часть жесткого диска читается несколько раз.
На мой взгляд, вариант 1) лучше, но использование SearchOption.AllDirectories в таких папках, как C: \, потребует огромных объемов памяти. Поэтому я бы просто сделал рекурсивный под-метод, который проходит через все подпапки, используя вариант 1)
Это должно вызывать только одну операцию GetFiles для каждой папки и, следовательно, быть быстрым (вариант 1), но использовать только небольшой объем памяти, поскольку фильтры применяются после чтения каждой подпапки -> служебные данные удаляются после каждой подпапки.
Пожалуйста, поправьте меня, если я ошибаюсь. Как я уже сказал, я новичок в программировании, но хочу получить более глубокое понимание вещей, чтобы в конечном итоге стать хорошим в этом :)
DirectoryInfo directory = new DirectoryInfo(Server.MapPath("~/Contents/"));
//Using Union
FileInfo[] files = directory.GetFiles("*.xlsx")
.Union(directory
.GetFiles("*.csv"))
.ToArray();
Как я могу просмотреть files, чтобы узнать путь? Спасибо
для
var exts = new[] { "mp3", "jpg" };
Ты мог бы:
public IEnumerable<string> FilterFiles(string path, params string[] exts) {
return
Directory
.EnumerateFiles(path, "*.*")
.Where(file => exts.Any(x => file.EndsWith(x, StringComparison.OrdinalIgnoreCase)));
}
Directory.EnumerateFiles для повышения производительности (В чем разница между Directory.EnumerateFiles и Directory.GetFiles?).EndsWith("aspx", StringComparison.OrdinalIgnoreCase), а не .ToLower().EndsWith("aspx"))Но реальное преимущество EnumerateFiles проявляется, когда вы разделяете фильтры и объединяете результаты:
public IEnumerable<string> FilterFiles(string path, params string[] exts) {
return
exts.Select(x => "*." + x) // turn into globs
.SelectMany(x =>
Directory.EnumerateFiles(path, x)
);
}
Это станет немного быстрее, если вам не нужно превращать их в шары (например, exts = new[] {"*.mp3", "*.jpg"}).
Оценка производительности на основе следующего теста LinqPad (примечание: Perf просто повторяет делегат 10000 раз)
https://gist.github.com/zaus/7454021
(репост и расширен из 'duplicate', поскольку этот вопрос специально не запрашивал LINQ: Несколько расширений файлов searchPattern для System.IO.Directory.GetFiles)
что вы имеете в виду, говоря «я стану немного быстрее, если вам не нужно превращать их в шары»? Это O (1) или O (n) (в отношении количества файлов, а не количества расширений)? Я бы предположил, что это O (1) (или O (n) в отношении количества расширений) и, вероятно, где-то в диапазоне нескольких циклов процессора ... Если это так, это, вероятно, - с точки зрения производительности - незначительно
@BatteryBackupUnit да, с 10 тыс. Повторений против 2 расширений разница между glob и str составляет 3 мс, так что да, технически незначительно (см. Ссылку на результаты производительности), но не зная, сколько расширений вам нужно отфильтровать, я решил, что стоит указать, что есть разница; Я оставляю вам решать, лучше ли «упрощенное использование» (например, .FilterFiles(path, "jpg", "gif")), чем «явное использование» (например, .FilterFiles(path, "*.jpg", "*.gif")).
отлично, спасибо. Извините, я как-то пропустил эту ссылку на github. Может мне стоит изменить настройки цвета экрана :)
Поддерживает ли это расширение в верхнем регистре, такое как .JPG или .MKV?
@Wahyu В моем первом примере вы заметите, что StringComparison.OrdinalIgnoreCase означает, что он будет работать с .jpg, .Jpg или .JPG и т. д.
Недостаток решения SelectMany заключается в том, что оно будет перебирать все файлы один раз для каждого переданного расширения файла.
@ 17of26 хороший звонок, спасибо, что указали на это. Забавно, потому что вчера я столкнулся с этим случаем и заметил это только потому, что у меня была куча файлов с «несколькими расширениями» (например, .json.html), которые соответствуют более чем одному глобу.
@ 17of26 Но я предполагаю / надеюсь, что, поскольку это больше связано с файловой системой с глобусом, он на самом деле не повторяет каждый файл в каталоге, по крайней мере, не в традиционном смысле.
Есть ловушка с EnumerateFiles, в которой соответствующие трехсимвольные расширения, такие как *.htm, также будут соответствовать *.html или действительно чему-либо, в котором есть .htm (например, .htmfoo). Похоже, это связано со старыми именами файлов DOS 8.3. codeproject.com/Questions/152289/… См. Примечание о searchPattern здесь: docs.microsoft.com/en-us/dotnet/api/…
@MichaelHaren, я не могу воспроизвести это локально в LinqPad 6 или в dotnetfiddle.net/U1zkoI (v4.7.2) - это привязано к определенной версии .NET?
Или вы можете просто преобразовать строку расширений в String ^
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;
}
Это C++, а не C#
в .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"))
{}
Что о
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);
Я не знаю, какое решение лучше, но я использую это:
String[] ext = "*.ext1|*.ext2".Split('|');
List<String> files = new List<String>();
foreach (String tmp in ext)
{
files.AddRange(Directory.GetFiles(dir, tmp, SearchOption.AllDirectories));
}
Если вы используете VB.NET (или импортировали зависимость в свой проект C#), на самом деле существует удобный метод, который позволяет фильтровать несколько расширений:
Microsoft.VisualBasic.FileIO.FileSystem.GetFiles("C:\path", Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, new string[] {"*.mp3", "*.jpg"});
В VB.NET к этому можно получить доступ через пространство имен My:
My.Computer.FileSystem.GetFiles("C:\path", FileIO.SearchOption.SearchAllSubDirectories, {"*.mp3", "*.jpg"})
К сожалению, эти удобные методы не поддерживают вариант с ленивой оценкой, как Directory.EnumerateFiles().
Это, пожалуй, лучший ответ, но все же принят более хитрый ответ. Должен так любить.
Использование шаблона поиска GetFiles для фильтрации расширения небезопасно !! Например, у вас есть два файла Test1.xls и Test2.xlsx, и вы хотите отфильтровать файл xls с помощью шаблона поиска * .xls, но GetFiles возвращает как Test1.xls, так и Test2.xlsx Я не знал об этом и получил ошибку в производственной среде, когда некоторые временные файлы внезапно стали обрабатываться как правильные. Шаблон поиска был * .txt, а временные файлы назывались * .txt20181028_100753898 Таким образом, шаблону поиска нельзя доверять, вам также нужно добавить дополнительную проверку имен файлов.
Не отвечает на вопрос.
Вот простой и элегантный способ получить отфильтрованные файлы
var allowedFileExtensions = ".csv,.txt";
var files = Directory.EnumerateFiles(@"C:\MyFolder", "*.*", SearchOption.TopDirectoryOnly)
.Where(s => allowedFileExtensions.IndexOf(Path.GetExtension(s)) > -1).ToArray();
В качестве примечания: использование шаблона поиска GetFiles для фильтрации расширения небезопасно. Например, у вас есть два файла Test1.xls и Test2.xlsx, и вы хотите отфильтровать файл xls с помощью шаблона поиска * .xls, но GetFiles возвращает оба файла Test1 .xls и Test2.xlsx. Прочтите раздел примечаний для получения дополнительной информации