К статье
Практический материал

Разработка и Конфигурация · 9 мин

Как перебрать все файлы в каталоге в 1С

Как перебрать файлы в каталоге в 1С: функция НайтиФайлы, рекурсивный обход подкаталогов, фильтрация по маске, работа с атрибутами файла и типичные ошибки.

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

Важно понимать контекст выполнения: файловые операции выполняются там, где работает код. Если обработка запускается на клиенте, путь указывается к диску пользователя; если на сервере — к диску сервера 1С, и права учётной записи сервера должны позволять чтение каталога. Это самая частая причина «пустого» результата при переносе обработки из файловой базы в клиент-серверную.

Базовый перебор файлов через НайтиФайлы

Функция НайтиФайлы() принимает три параметра: путь к каталогу, маску поиска и признак поиска в подкаталогах. Минимальный вариант — только путь, тогда вернутся все файлы и подкаталоги первого уровня.

НайденныеФайлы = НайтиФайлы("D:\Обмен", "*.xml", Ложь);

Для Каждого Файл Из НайденныеФайлы Цикл

Если Не Файл.ЭтоКаталог() Тогда

Сообщить(Файл.ПолноеИмя);

КонецЕсли;

КонецЦикла;

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

Фильтрация по маске и нескольким расширениям

Маска поддерживает символы (любая последовательность) и ? (один символ). Через точку с запятой можно указать несколько масок: ".xml;*.txt". Если нужен отбор по условию, которого нет в маске, фильтруйте уже внутри цикла.

НайденныеФайлы = НайтиФайлы(КаталогОбмена, ".xml;.csv");

Для Каждого Файл Из НайденныеФайлы Цикл

Если Файл.ЭтоКаталог() Тогда

Продолжить;

КонецЕсли;

// Дополнительный фильтр: только файлы, изменённые сегодня

Если НачалоДня(Файл.ПолучитьВремяИзменения()) = НачалоДня(ТекущаяДата()) Тогда

ОбработатьФайл(Файл.ПолноеИмя);

КонецЕсли;

КонецЦикла;

Учтите, что регистр символов в маске зависит от файловой системы: на Windows .XML и .xml эквивалентны, на Linux — нет. Если обработка должна работать кроссплатформенно, безопаснее сравнивать расширение программно через НРег(Файл.Расширение).

Рекурсивный обход подкаталогов

Простейший способ обойти вложенные папки — передать Истина третьим параметром НайтиФайлы. Функция вернёт плоский массив всех найденных объектов из всего дерева каталогов.

// Все файлы в каталоге и во всех подкаталогах

НайденныеФайлы = НайтиФайлы(КорневойКаталог, ".", Истина);

Когда нужен контроль над структурой — например, обработать каждый подкаталог отдельно или построить дерево в интерфейсе, — используйте явную рекурсию:

Процедура ОбойтиКаталог(Путь)

НайденныеФайлы = НайтиФайлы(Путь, ".");

Для Каждого Файл Из НайденныеФайлы Цикл

Если Файл.ЭтоКаталог() Тогда

ОбойтиКаталог(Файл.ПолноеИмя); // рекурсивный вызов

Иначе

ОбработатьФайл(Файл.ПолноеИмя);

КонецЕсли;

КонецЦикла;

КонецПроцедуры

Перебор файлов на клиенте и на сервере

В управляемом приложении директивы компиляции определяют, где выполняется код. Если обработка открывается на клиенте пользователя и читает локальные файлы, помечайте метод &НаКлиенте. Если файлы лежат на сервере (типовой сценарий регламентного обмена) — &НаСервере или &НаСервереБезКонтекста.

При работе в тонком или веб-клиенте прямой доступ к диску пользователя ограничен. Для загрузки файлов с клиента на сервер используется НачатьПомещениеФайлаНаСервер или передача через временное хранилище. Если нужно, чтобы пользователь сам выбрал каталог, примените ДиалогВыбораФайла в режиме РежимДиалогаВыбораФайла.ВыборКаталога.

&НаКлиенте

Процедура ВыбратьИОбработать(Команда)

Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);

Диалог.Заголовок = "Выберите каталог с файлами";

Если Диалог.Выбрать() Тогда

НайденныеФайлы = НайтиФайлы(Диалог.Каталог, "*.xml");

Для Каждого Файл Из НайденныеФайлы Цикл

Сообщить(Файл.Имя);

КонецЦикла;

КонецЕсли;

КонецПроцедуры

Маршрут решения

Как выбрать действие

Файлы лежат на компьютере пользователяВыполняйте НайтиФайлы на клиенте или передавайте файлы на сервер через временное хранилище
Файлы в сетевой папке, доступной серверу 1СВыполняйте перебор на сервере, проверив права учётной записи службы сервера
Нужен обход сотен тысяч файлов по расписаниюОформите как фоновое задание с записью прогресса в журнал регистрации

Проверка существования каталога и обработка ошибок

Перед перебором убедитесь, что каталог существует, иначе НайтиФайлы вернёт пустой массив или вызовет исключение в зависимости от ситуации. Проверка выполняется через объект Файл и метод Существует().

Каталог = Новый Файл(ПутьККаталогу);

Если Не Каталог.Существует() Тогда

ВызватьИсключение "Каталог не найден: " + ПутьККаталогу;

КонецЕсли;

Попытка

НайденныеФайлы = НайтиФайлы(ПутьККаталогу, ".");

Исключение

ЗаписьЖурналаРегистрации("Обмен", УровеньЖурналаРегистрации.Ошибка,,,

ОписаниеОшибки());

Возврат;

КонецПопытки;

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

Типичные ошибки
01
Не проверяется ЭтоКаталог() — обработка пытается открыть папку как файл и падает с ошибкой
02
Код с НайтиФайлы перенесён на сервер, а путь остался клиентским (C:\...) — массив пустой, ошибок нет
03
Маска задана с учётом регистра, а база работает на Linux — часть файлов не находится
04
Нет обработки исключений внутри цикла — один заблокированный файл прерывает обработку всего каталога
05
Рекурсивный обход запущен по корню диска — сеанс зависает надолго

Альтернативы и смежные задачи

Если нужно не обработать, а показать пользователю дерево файлов, результат НайтиФайлы удобно загрузить в ДеревоЗначений и вывести на форму. Для однократной проверки содержимого каталога без кода подойдёт стандартный диалог выбора файла.

Для удаления обработанных файлов используйте УдалитьФайлы(Путь, Маска), для перемещения — ПереместитьФайл(). Типовой приём надёжного обмена: после успешной загрузки перемещать файл в подкаталог «Архив», чтобы при повторном запуске он не обрабатывался снова.

Контрольные точки

Как проверить результат

Количество найденных файлов
Норма

Совпадает с числом файлов в проводнике при той же маске

Тревожный признак

Массив пустой или файлов меньше — проверьте путь, маску и контекст выполнения

Обработка каждого файла
Норма

Для каждого файла есть запись в журнале или результат загрузки

Тревожный признак

Часть файлов пропущена без сообщений — нет обработки исключений

Повторный запуск
Норма

Обработанные файлы не загружаются повторно (перемещены или учтены)

Тревожный признак

Данные дублируются при каждом запуске

Частые вопросы

НайтиФайлы возвращает пустой массив, хотя файлы в папке есть. В чём причина?

Чаще всего код выполняется на сервере, а путь указывает на локальный диск клиента, либо у учётной записи сервера 1С нет прав на сетевую папку. Проверьте контекст выполнения (директивы &НаКлиенте/&НаСервере) и права доступа к каталогу.

Как перебрать только файлы, без подкаталогов?

Вызовите НайтиФайлы без третьего параметра (или с Ложь) и внутри цикла пропускайте элементы, для которых ЭтоКаталог() возвращает Истина. Альтернатива — проверка ЭтоФайл().

Как отсортировать найденные файлы по дате изменения?

Загрузите массив в ТаблицуЗначений с колонками «Файл» и «ВремяИзменения» (через ПолучитьВремяИзменения()), затем вызовите метод Сортировать("ВремяИзменения") и обходите уже таблицу.

Можно ли использовать НайтиФайлы в фоновом задании?

Да, это типовой сценарий для регламентной загрузки. Код выполняется на сервере, поэтому каталог должен быть доступен с сервера 1С. Ход обработки фиксируйте через ЗаписьЖурналаРегистрации или служебный регистр сведений.

Как получить только расширение файла без точки?

Свойство Файл.Расширение возвращает расширение с точкой (например, ".xml"). Для сравнения используйте НРег(Файл.Расширение) = ".xml" или отсеките точку через Сред(Файл.Расширение, 2).

Что делать, если файл заблокирован другой программой во время обработки?

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

Итог

Что важно запомнить

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