Как найти файлы с несколькими расширениями одновременно в 1С:Предприятие

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

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

Различие между Маской и Фильтром

Прежде всего, проанализируем, почему конструкция вида "*.jpg;*.pdf" не работает. В языке 1С маска поиска для функции НайтиФайлы строится по правилам операционной системы (или упрощенному POSIX). Она допускает использование подстановочных знаков, таких как * (любое количество символов) и ? (один любой символ), а также классов символов в квадратных скобках. Однако символ | или ; воспринимается системой как часть имени файла, а не как разделитель форматов. Поэтому нам придется использовать обходные пути.

Способ 1: Использование цикла по массиву масок

Это самый прозрачный и надежный метод. Если нам заранее известен список расширений, мы можем создать массив этих расширений и вызывать функцию НайтиФайлы в цикле. Рассмотрим этот пример подробнее:


ИмяКаталога = "C:\Documents\FilesToProcess";
ИскатьВПодкаталогах = Истина;

МассивМасок = Новый Массив;
МассивМасок.Добавить("*.jpg");
МассивМасок.Добавить("*.pdf");
МассивМасок.Добавить("*.png");

МассивФайлов = Новый Массив;

Для Каждого Маска Из МассивМасок Цикл
    НайденныеФайлы = НайтиФайлы(ИмяКаталога, Маска, ИскатьВПодкаталогах);
    
    // Если используется БСП, можно применить ОбщегоНазначения.ЗаполнитьМассивУникальнымиЗначениями
    Для Каждого ТекущийФайл Из НайденныеФайлы Цикл
        МассивФайлов.Добавить(ТекущийФайл);
    КонецЦикла;
КонецЦикла;

Если МассивФайлов.Количество() > 0 Тогда
    Для Каждого ЭлементФайл Из МассивФайлов Цикл
        Сообщить("Найден файл: " + ЭлементФайл.Имя);
    КонецЦикла;
Иначе
    Сообщить("Файлы указанных типов не найдены.");
КонецЕсли;

Важный нюанс: при таком подходе, если маски пересекаются (например, "*.doc" и "*.*"), в итоговый массив могут попасть дубликаты. Чтобы этого избежать, рекомендуем проверять наличие файла в результирующем массиве или использовать соответствие для хранения уникальных путей.

Способ 2: Получение всех файлов с последующей фильтрацией

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


ПутьКПапке = "D:\Data\Upload";
СписокНужныхРасширений = ".JPG, .JPEG, .PDF, .PNG"; // Список в верхнем регистре для сравнения
НайденныеОбъекты = НайтиФайлы(ПутьКПапке, "*.*", Ложь);

МассивРезультат = Новый Массив;

Для Каждого ТекущийОбъект Из НайденныеОбъекты Цикл
    // Исключаем каталоги из поиска
    Если ТекущийОбъект.ЭтоКаталог() Тогда
        Продолжить;
    КонецЕсли;
    
    РасширениеФайла = ВРЕГ(ТекущийОбъект.Расширение); // Приводим к верхнему регистру
    
    Если СтрНайти(СписокНужныхРасширений, РасширениеФайла) > 0 Тогда
        МассивРезультат.Добавить(ТекущийОбъект);
    КонецЕсли;
КонецЦикла;

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

Способ 3: Современный асинхронный поиск (платформа 8.3.15+)

Для мобильных приложений и веб-клиентов, а также для предотвращения блокировки интерфейса в тонком клиенте, следует использовать асинхронные методы. Разберем, как это работает на примере НайтиФайлыАсинх. Принцип работы с масками остается прежним, но результат мы получаем через объект Обещание.


&НаКлиенте
АсинхроннаяПроцедура ПоискФайловНаСервере()
    
    КаталогПоиска = "C:\Temp";
    МассивРезультатов = Новый Массив;
    
    // Выполняем поиск для первого расширения
    РезультатPDF = Ждать НайтиФайлыАсинх(КаталогПоиска, "*.pdf");
    Для Каждого Файл Из РезультатPDF Цикл
        МассивРезультатов.Добавить(Файл);
    КонецЦикла;
    
    // Выполняем поиск для второго расширения
    РезультатJPG = Ждать НайтиФайлыАсинх(КаталогПоиска, "*.jpg");
    Для Каждого Файл Из РезультатJPG Цикл
        МассивРезультатов.Добавить(Файл);
    КонецЦикла;
    
    // Дальнейшая обработка массива
КонецПроцедуры

Особенности работы на ОС Linux и кроссплатформенность

Выясним причину, по которой поиск может не работать при переносе базы на сервер под управлением Linux. В ОС Windows файловая система нечувствительна к регистру (case-insensitive), поэтому маска "*.jpg" найдет и "image.JPG". В Linux маска "*.jpg" не найдет файлы с расширением в верхнем регистре.

Чтобы обеспечить кроссплатформенность, мы можем использовать квадратные скобки в маске:

Производительность и оптимизация

Рассмотрим рекомендации по выбору метода в зависимости от условий:

  1. Огромное количество файлов в папке: Если в директории лежат миллионы файлов разных типов, используйте Способ 1 (цикл по маскам). Это позволит операционной системе вернуть только нужные записи, не перегружая память 1С объектами Файл для ненужных расширений.
  2. Небольшие папки или сетевые диски: Используйте Способ 2 (поиск всех файлов). Одиночное сканирование каталога обычно быстрее, чем серия последовательных запросов по сети.
  3. Глубокая иерархия подпапок: При использовании параметра Истина в рекурсивном поиске помните, что 1С обходит все дерево. Если файлы лежат в конкретных подпапках, лучше сначала составить список этих подпапок, а затем запустить поиск в каждой из них.

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

← На главную