Разработка и Конфигурация · 9 мин
Как перебрать все файлы в каталоге в 1С
Как перебрать файлы в каталоге в 1С: функция НайтиФайлы, рекурсивный обход подкаталогов, фильтрация по маске, работа с атрибутами файла и типичные ошибки.
Перебор файлов в каталоге — типовая задача при загрузке прайсов, обмене с банками, обработке выгрузок из других систем и пакетной обработке документов. Во встроенном языке 1С для этого предназначена функция НайтиФайлы(), которая возвращает массив объектов типа Файл, и объекты ОбходДереваДанных не требуются — достаточно простого цикла. Ниже разобраны рабочие варианты кода для толстого, тонкого и веб-клиента, с фильтрацией по маске и рекурсивным обходом подкаталогов.
Важно понимать контекст выполнения: файловые операции выполняются там, где работает код. Если обработка запускается на клиенте, путь указывается к диску пользователя; если на сервере — к диску сервера 1С, и права учётной записи сервера должны позволять чтение каталога. Это самая частая причина «пустого» результата при переносе обработки из файловой базы в клиент-серверную.
Базовый перебор файлов через НайтиФайлы
Функция НайтиФайлы() принимает три параметра: путь к каталогу, маску поиска и признак поиска в подкаталогах. Минимальный вариант — только путь, тогда вернутся все файлы и подкаталоги первого уровня.
НайденныеФайлы = НайтиФайлы("D:\Обмен", "*.xml", Ложь);
Для Каждого Файл Из НайденныеФайлы Цикл
Если Не Файл.ЭтоКаталог() Тогда
Сообщить(Файл.ПолноеИмя);
КонецЕсли;
КонецЦикла;
Каждый элемент массива — объект Файл с полезными свойствами: Имя (имя с расширением), ИмяБезРасширения, Расширение, ПолноеИмя (полный путь), Путь (каталог), Размер() и ПолучитьВремяИзменения(). Методы ЭтоКаталог() и ЭтоФайл() позволяют отличить папку от файла.
Фильтрация по маске и нескольким расширениям
Маска поддерживает символы (любая последовательность) и ? (один символ). Через точку с запятой можно указать несколько масок: ".xml;*.txt". Если нужен отбор по условию, которого нет в маске, фильтруйте уже внутри цикла.
НайденныеФайлы = НайтиФайлы(КаталогОбмена, ".xml;.csv");
Для Каждого Файл Из НайденныеФайлы Цикл
Если Файл.ЭтоКаталог() Тогда
Продолжить;
КонецЕсли;
// Дополнительный фильтр: только файлы, изменённые сегодня
Если НачалоДня(Файл.ПолучитьВремяИзменения()) = НачалоДня(ТекущаяДата()) Тогда
ОбработатьФайл(Файл.ПолноеИмя);
КонецЕсли;
КонецЦикла;
Учтите, что регистр символов в маске зависит от файловой системы: на Windows .XML и .xml эквивалентны, на Linux — нет. Если обработка должна работать кроссплатформенно, безопаснее сравнивать расширение программно через НРег(Файл.Расширение).
Рекурсивный обход подкаталогов
Простейший способ обойти вложенные папки — передать Истина третьим параметром НайтиФайлы. Функция вернёт плоский массив всех найденных объектов из всего дерева каталогов.
// Все файлы в каталоге и во всех подкаталогах
НайденныеФайлы = НайтиФайлы(КорневойКаталог, ".", Истина);
Когда нужен контроль над структурой — например, обработать каждый подкаталог отдельно или построить дерево в интерфейсе, — используйте явную рекурсию:
Процедура ОбойтиКаталог(Путь)
НайденныеФайлы = НайтиФайлы(Путь, ".");
Для Каждого Файл Из НайденныеФайлы Цикл
Если Файл.ЭтоКаталог() Тогда
ОбойтиКаталог(Файл.ПолноеИмя); // рекурсивный вызов
Иначе
ОбработатьФайл(Файл.ПолноеИмя);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Перебор файлов на клиенте и на сервере
В управляемом приложении директивы компиляции определяют, где выполняется код. Если обработка открывается на клиенте пользователя и читает локальные файлы, помечайте метод &НаКлиенте. Если файлы лежат на сервере (типовой сценарий регламентного обмена) — &НаСервере или &НаСервереБезКонтекста.
При работе в тонком или веб-клиенте прямой доступ к диску пользователя ограничен. Для загрузки файлов с клиента на сервер используется НачатьПомещениеФайлаНаСервер или передача через временное хранилище. Если нужно, чтобы пользователь сам выбрал каталог, примените ДиалогВыбораФайла в режиме РежимДиалогаВыбораФайла.ВыборКаталога.
&НаКлиенте
Процедура ВыбратьИОбработать(Команда)
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
Диалог.Заголовок = "Выберите каталог с файлами";
Если Диалог.Выбрать() Тогда
НайденныеФайлы = НайтиФайлы(Диалог.Каталог, "*.xml");
Для Каждого Файл Из НайденныеФайлы Цикл
Сообщить(Файл.Имя);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Как выбрать действие
Проверка существования каталога и обработка ошибок
Перед перебором убедитесь, что каталог существует, иначе НайтиФайлы вернёт пустой массив или вызовет исключение в зависимости от ситуации. Проверка выполняется через объект Файл и метод Существует().
Каталог = Новый Файл(ПутьККаталогу);
Если Не Каталог.Существует() Тогда
ВызватьИсключение "Каталог не найден: " + ПутьККаталогу;
КонецЕсли;
Попытка
НайденныеФайлы = НайтиФайлы(ПутьККаталогу, ".");
Исключение
ЗаписьЖурналаРегистрации("Обмен", УровеньЖурналаРегистрации.Ошибка,,,
ОписаниеОшибки());
Возврат;
КонецПопытки;
Отдельно обрабатывайте ошибки доступа к конкретным файлам внутри цикла: файл может быть заблокирован другой программой в момент чтения. Оберните тело обработки в Попытка...Исключение, чтобы один «плохой» файл не прервал весь перебор.
Альтернативы и смежные задачи
Если нужно не обработать, а показать пользователю дерево файлов, результат НайтиФайлы удобно загрузить в ДеревоЗначений и вывести на форму. Для однократной проверки содержимого каталога без кода подойдёт стандартный диалог выбора файла.
Для удаления обработанных файлов используйте УдалитьФайлы(Путь, Маска), для перемещения — ПереместитьФайл(). Типовой приём надёжного обмена: после успешной загрузки перемещать файл в подкаталог «Архив», чтобы при повторном запуске он не обрабатывался снова.
Как проверить результат
Совпадает с числом файлов в проводнике при той же маске
Массив пустой или файлов меньше — проверьте путь, маску и контекст выполнения
Для каждого файла есть запись в журнале или результат загрузки
Часть файлов пропущена без сообщений — нет обработки исключений
Обработанные файлы не загружаются повторно (перемещены или учтены)
Данные дублируются при каждом запуске
Частые вопросы
НайтиФайлы возвращает пустой массив, хотя файлы в папке есть. В чём причина?
Чаще всего код выполняется на сервере, а путь указывает на локальный диск клиента, либо у учётной записи сервера 1С нет прав на сетевую папку. Проверьте контекст выполнения (директивы &НаКлиенте/&НаСервере) и права доступа к каталогу.
Как перебрать только файлы, без подкаталогов?
Вызовите НайтиФайлы без третьего параметра (или с Ложь) и внутри цикла пропускайте элементы, для которых ЭтоКаталог() возвращает Истина. Альтернатива — проверка ЭтоФайл().
Как отсортировать найденные файлы по дате изменения?
Загрузите массив в ТаблицуЗначений с колонками «Файл» и «ВремяИзменения» (через ПолучитьВремяИзменения()), затем вызовите метод Сортировать("ВремяИзменения") и обходите уже таблицу.
Можно ли использовать НайтиФайлы в фоновом задании?
Да, это типовой сценарий для регламентной загрузки. Код выполняется на сервере, поэтому каталог должен быть доступен с сервера 1С. Ход обработки фиксируйте через ЗаписьЖурналаРегистрации или служебный регистр сведений.
Как получить только расширение файла без точки?
Свойство Файл.Расширение возвращает расширение с точкой (например, ".xml"). Для сравнения используйте НРег(Файл.Расширение) = ".xml" или отсеките точку через Сред(Файл.Расширение, 2).
Что делать, если файл заблокирован другой программой во время обработки?
Оберните чтение файла в Попытка...Исключение внутри цикла, запишите ошибку в журнал регистрации и продолжите со следующим файлом. При необходимости реализуйте повторную попытку через паузу или отложите файл в очередь на следующий запуск.
Что важно запомнить
Перебор файлов выполняется через НайтиФайлы(Путь, Маска, ИскатьВПодкаталогах) с обходом результата в цикле. Всегда различайте файлы и каталоги, проверяйте существование пути, учитывайте контекст выполнения (клиент/сервер) и обрабатывайте исключения внутри цикла, чтобы один проблемный файл не прервал всю обработку.