В процессе разработки на платформе 1С:Предприятие часто возникает задача программного поиска файлов в каталогах. Однако стандартный метод НайтиФайлы таит в себе несколько нюансов, которые могут запутать даже опытного разработчика. Чаще всего проблемы возникают при попытке отсечь папки из результатов поиска или при необходимости найти файлы сразу нескольких типов (например, и .xls, и .xlsx). Рассмотрим подробно, почему возникают эти сложности и как их правильно решать.
Разберем ситуацию: разработчик вызывает НайтиФайлы(ПутьККаталогу, "*.*", Истина) и ожидает получить только файлы. На практике же в массив результатов попадают и вложенные каталоги. Выясним причину такого поведения. В операционной системе Windows маска *.* исторически означает "любое имя и любое расширение". Поскольку каталог в файловой системе — это тоже объект, Windows возвращает его по этой маске, даже если у каталога нет точки в названии.
Для того чтобы гарантированно получить только файлы, мы не можем полагаться исключительно на маску. Проанализируем объект Файл, который возвращается в массиве результатов. У этого объекта есть встроенные методы для идентификации типа объекта. Единственный надежный способ — это постобработка полученного массива.
Рассмотрим правильный алгоритм обхода результатов поиска. Вместо того чтобы пытаться составить "идеальную" маску, мы проверим каждый найденный объект на принадлежность к файлам. Посмотрим на пример кода:
НайденныеОбъекты = НайтиФайлы(ПутьККаталогу, "*.*", Истина);
ТолькоФайлы = Новый Массив;
Для Каждого ТекущийОбъект Из НайденныеОбъекты Цикл
// Метод ЭтоФайл() возвращает Истина, если объект не является каталогом
Если ТекущийОбъект.ЭтоФайл() Тогда
ТолькоФайлы.Добавить(ТекущийОбъект);
КонецЕсли;
КонецЦикла;
Этот подход является универсальным и работает корректно во всех версиях платформы 1С и во всех операционных системах. Мы сначала получаем "широкую" выборку, а затем сужаем её до необходимых нам объектов.
Часто возникает заблуждение, что в методе НайтиФайлы можно указать несколько масок через точку с запятой, например: "*.txt;*.log". Важно понимать различие: такая конструкция работает в объекте ДиалогВыбораФайла (интерактивном окне), но не поддерживается методом НайтиФайлы в среде Windows. Если передать такую строку в поиск, система либо ничего не найдет, либо выдаст ошибку.
Для реализации поиска по нескольким маскам проанализируем следующий подход: нам необходимо создать функцию-обертку, которая будет последовательно вызывать поиск для каждой маски и объединять результаты в один массив. Разберем реализацию такой функции:
&НаСервере
Функция ПоискФайловПоСпискуМасок(КаталогПоиска, СтрокаМасок)
// СтрокаМасок может быть в формате "*.jpg;*.png;*.gif"
МассивМасок = СтрРазделить(СтрокаМасок, ";");
ИтоговыйМассив = Новый Массив;
Для Каждого ТекущаяМаска Из МассивМасок Цикл
// Очищаем маску от лишних пробелов, если они есть
ЧистаяМаска = СокрЛП(ТекущаяМаска);
РезультатПоиска = НайтиФайлы(КаталогПоиска, ЧистаяМаска, Ложь);
Для Каждого НайденныйФайл Из РезультатПоиска Цикл
// Добавляем проверку, чтобы не было дублей, и фильтруем папки
Если НайденныйФайл.ЭтоФайл() Тогда
ИтоговыйМассив.Добавить(НайденныйФайл);
КонецЕсли;
КонецЦикла;
КонецЦикла;
Возврат ИтоговыйМассив;
КонецФункции
Проанализируем технические различия, которые зависят от окружения, в котором выполняется код. Это критически важно, если ваша конфигурация работает на сервере под Linux или вы разрабатываете под мобильную платформу.
* (любое количество символов) и ? (один любой символ). Регистр символов в маске значения не имеет.*.[jJ][pP][gG] позволит найти файлы с расширением jpg в любом регистре (JPG, jpg, Jpg). По умолчанию поиск в Linux регистрозависимый.Рассмотрим пример для Linux, если нам нужно найти файлы с расширениями .erp или .epf одной командой:
// Данная конструкция будет работать только на Linux/macOS
Результат = НайтиФайлы(Каталог, "*.e[pr][fp]");
В Windows этот же код не вернет результатов, поэтому для кроссплатформенности лучше использовать универсальный метод с циклом, описанный выше.
Если задача требует очень сложного отбора (например, найти файлы, имя которых начинается на "INV", содержит цифры и имеет расширение pdf или docx), возможностей стандартной маски не хватит. В версиях платформы 1С 8.3.23 и выше появился встроенный объект РегулярныеВыражения. Рассмотрим стратегию совместной работы поиска и регулярок:
*).ЭтоФайл().ОбъектФайл.Имя) на соответствие регулярному выражению.Это позволяет реализовать фильтрацию любой сложности без многократного обращения к файловой системе, что значительно повышает производительность.
При работе с файловой системой следует всегда учитывать два важных момента: права доступа и отзывчивость интерфейса.
Попытка и Исключение: Процесс поиска может прерваться ошибкой, если у пользователя нет прав на чтение одной из вложенных папок. Обязательно оборачивайте вызов в конструкцию Попытка ... Исключение.
Асинхронность: В управляемом приложении (особенно в веб-клиенте) выполнение НайтиФайлы может привести к зависанию формы. Проанализируем современный стандарт разработки: рекомендуется использовать метод НайтиФайлыАсинх. Он возвращает Обещание и не блокирует работу пользователя во время сканирования больших дисковых пространств.
Подведем итог: для надежной работы используйте метод ЭтоФайл() для отсечения папок и программный перебор массива масок для поиска файлов разных типов. Это гарантирует стабильную работу вашего кода в любых условиях эксплуатации.