Ошибка "Незаконные символы в пути" с использованием подстановочных знаков с помощью Directory.GetFiles

У меня есть каталог с несколькими подкаталогами, которые содержат файлы .doc. Пример:

C:\Users\user\Documents\testenviroment\Released\test0.doc
C:\Users\user\Documents\testenviroment\Debug\test1.doc
C:\Users\user\Documents1\testenviroment\Debug\test2.doc
C:\Users\user\Documents1\testenviroment\Released\test20.doc

Я хочу получить все файлы test*.doc во всех папках отладки. Я пробовал:

string[] files = Directory.GetFiles(@"C:\Users\user", "*Debug\\test*.doc",
    SearchOption.AllDirectories);

И это дает мне ошибку "Недопустимые символы в пути".

Если я попробую:

string[] files = Directory.GetFiles(@"C:\Users\user", "\\Debug\\test*.doc",
    SearchOption.AllDirectories); 

Я получаю другую ошибку: "Не удалось найти часть пути C:\Users\user\Debug".

Ответ 1

Вы включаете папку в шаблон поиска, который не ожидается. Согласно docs:

searchPattern Тип: System.String Строка поиска для соответствия имена файлов в пути. Этот параметр может содержать комбинацию действительных буквенных путей и символов подстановки (* и?) (см. Примечания), но не поддерживает регулярные выражения.

С учетом этого попробуйте что-то вроде этого:

String[] files = Directory.GetFiles(@"C:\Users\user", "test*.doc", SearchOption.AllDirectories)
                 .Where(file => file.Contains("\\Debug\\"))
                 .ToArray();

Это приведет к получению ВСЕХ файлов в указанном каталоге и возвращает их с помощью Debug в пути. Имея это в виду, постарайтесь, чтобы каталог поиска был сужен как можно больше.

Примечание:

В мой первоначальный ответ включен EnumerateFiles, который будет работать следующим образом (убедитесь, что вы передали поиск (спасибо @CodeCaster)):

String[] files = Directory.EnumerateFiles(@"C:\Users\user", "test*.doc", SearchOption.AllDirectories)
                 .Where(file => file.Contains("\\Debug\\"))
                 .ToArray();

Я только что запустил тест, а второй, кажется, медленнее, но может быть быстрее в большой папке. Стоит иметь в виду.

Изменить: примечание от @pinkfloydx33

На самом деле у меня это фактически сняло систему, которую я по наследству. Это заняло много времени, пытаясь вернуть массив и убивая также память. Проблема была отклонена преобразованием к перечислимым коллегам

Таким образом, использование второго варианта будет более безопасным для больших каталогов.

Ответ 2

Второй параметр, шаблон поиска, работает только для имен файлов. Таким образом, вам нужно будет перебирать каталоги, которые вы хотите выполнить, а затем вызвать Directory.GetFiles(directory, "test*.doc") в каждом каталоге.

Как написать этот код, зависит от того, насколько он вам нужен и какие предположения вы хотите сделать (например, "все каталоги Debug всегда находятся в двух уровнях в каталоге пользователя" по сравнению с "каталогом Debug" может быть на любом уровне в каталог пользователя ").

Смотрите Как рекурсивно перечислить все файлы в каталоге на С#?.

В качестве альтернативы, если вы хотите искать все подкаталоги, а затем отбрасывать файлы, которые не соответствуют вашим предпочтениям, см. Рекурсивный поиск файла в каталогах:

var files = Directory.GetFiles(@"C:\Users\user", "test*.doc", SearchOption.AllDirectories)
               .Where(f => f.IndexOf(@"\debug", StringComparison.OrdinalIgnoreCase) >= 0);

Но обратите внимание, что это может быть плохо для производительности, поскольку оно сканирует нерелевантные каталоги.