Как правильно использовать маску в функции НайтиФайлы и отфильтровать только файлы?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки на платформе 1С:Предприятие часто возникает задача программного поиска файлов в каталогах. Однако стандартный метод НайтиФайлы таит в себе несколько нюансов, которые могут запутать даже опытного разработчика. Чаще всего проблемы возникают при попытке отсечь папки из результатов поиска или при необходимости найти файлы сразу нескольких типов (например, и .xls, и .xlsx). Рассмотрим подробно, почему возникают эти сложности и как их правильно решать.

Причина некорректной работы маски "*.*"

Разберем ситуацию: разработчик вызывает НайтиФайлы(ПутьККаталогу, "*.*", Истина) и ожидает получить только файлы. На практике же в массив результатов попадают и вложенные каталоги. Выясним причину такого поведения. В операционной системе Windows маска *.* исторически означает "любое имя и любое расширение". Поскольку каталог в файловой системе — это тоже объект, Windows возвращает его по этой маске, даже если у каталога нет точки в названии.

Для того чтобы гарантированно получить только файлы, мы не можем полагаться исключительно на маску. Проанализируем объект Файл, который возвращается в массиве результатов. У этого объекта есть встроенные методы для идентификации типа объекта. Единственный надежный способ — это постобработка полученного массива.

Решение 1: Фильтрация файлов через метод ЭтоФайл()

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


НайденныеОбъекты = НайтиФайлы(ПутьККаталогу, "*.*", Истина);
ТолькоФайлы = Новый Массив;

Для Каждого ТекущийОбъект Из НайденныеОбъекты Цикл
    // Метод ЭтоФайл() возвращает Истина, если объект не является каталогом
    Если ТекущийОбъект.ЭтоФайл() Тогда
        ТолькоФайлы.Добавить(ТекущийОбъект);
    КонецЕсли;
КонецЦикла;

Этот подход является универсальным и работает корректно во всех версиях платформы 1С и во всех операционных системах. Мы сначала получаем "широкую" выборку, а затем сужаем её до необходимых нам объектов.

Решение 2: Поиск по нескольким расширениям одновременно

Часто возникает заблуждение, что в методе НайтиФайлы можно указать несколько масок через точку с запятой, например: "*.txt;*.log". Важно понимать различие: такая конструкция работает в объекте ДиалогВыбораФайла (интерактивном окне), но не поддерживается методом НайтиФайлы в среде Windows. Если передать такую строку в поиск, система либо ничего не найдет, либо выдаст ошибку.

Для реализации поиска по нескольким маскам проанализируем следующий подход: нам необходимо создать функцию-обертку, которая будет последовательно вызывать поиск для каждой маски и объединять результаты в один массив. Разберем реализацию такой функции:


&НаСервере
Функция ПоискФайловПоСпискуМасок(КаталогПоиска, СтрокаМасок)
    // СтрокаМасок может быть в формате "*.jpg;*.png;*.gif"
    МассивМасок = СтрРазделить(СтрокаМасок, ";");
    ИтоговыйМассив = Новый Массив;
    
    Для Каждого ТекущаяМаска Из МассивМасок Цикл
        // Очищаем маску от лишних пробелов, если они есть
        ЧистаяМаска = СокрЛП(ТекущаяМаска);
        РезультатПоиска = НайтиФайлы(КаталогПоиска, ЧистаяМаска, Ложь);
        
        Для Каждого НайденныйФайл Из РезультатПоиска Цикл
            // Добавляем проверку, чтобы не было дублей, и фильтруем папки
            Если НайденныйФайл.ЭтоФайл() Тогда
                ИтоговыйМассив.Добавить(НайденныйФайл);
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
    
    Возврат ИтоговыйМассив;
КонецФункции

Особенности работы в разных операционных системах

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

  1. Windows: Маска ограничена символами * (любое количество символов) и ? (один любой символ). Регистр символов в маске значения не имеет.
  2. Linux и macOS: Здесь возможности маски гораздо шире. Можно использовать классы символов в квадратных скобках. Например, маска *.[jJ][pP][gG] позволит найти файлы с расширением jpg в любом регистре (JPG, jpg, Jpg). По умолчанию поиск в Linux регистрозависимый.
  3. Мобильные платформы (iOS, Android): Поиск обычно нечувствителен к регистру и также поддерживает использование квадратных скобок для задания диапазонов.

Рассмотрим пример для Linux, если нам нужно найти файлы с расширениями .erp или .epf одной командой:


// Данная конструкция будет работать только на Linux/macOS
Результат = НайтиФайлы(Каталог, "*.e[pr][fp]");

В Windows этот же код не вернет результатов, поэтому для кроссплатформенности лучше использовать универсальный метод с циклом, описанный выше.

Использование регулярных выражений для сложной фильтрации

Если задача требует очень сложного отбора (например, найти файлы, имя которых начинается на "INV", содержит цифры и имеет расширение pdf или docx), возможностей стандартной маски не хватит. В версиях платформы 1С 8.3.23 и выше появился встроенный объект РегулярныеВыражения. Рассмотрим стратегию совместной работы поиска и регулярок:

  1. Выполняем поиск по максимально широкой маске (например, *).
  2. В цикле обхода проверяем ЭтоФайл().
  3. Дополнительно проверяем имя файла (ОбъектФайл.Имя) на соответствие регулярному выражению.

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

Безопасность и асинхронность

При работе с файловой системой следует всегда учитывать два важных момента: права доступа и отзывчивость интерфейса.

Попытка и Исключение: Процесс поиска может прерваться ошибкой, если у пользователя нет прав на чтение одной из вложенных папок. Обязательно оборачивайте вызов в конструкцию Попытка ... Исключение.

Асинхронность: В управляемом приложении (особенно в веб-клиенте) выполнение НайтиФайлы может привести к зависанию формы. Проанализируем современный стандарт разработки: рекомендуется использовать метод НайтиФайлыАсинх. Он возвращает Обещание и не блокирует работу пользователя во время сканирования больших дисковых пространств.

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

← На главную