Как скопировать каталог и его содержимое средствами 1С: способы и примеры кода

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

В процессе разработки на платформе 1С часто возникает задача копирования не просто отдельного файла, а целого каталога со всей его иерархией. Стандартного метода вроде КопироватьКаталог() в языке 1С не существует, поэтому разработчики используют различные обходные пути: от рекурсивного обхода папок до вызова системных утилит Windows или Linux. В этой статье мы подробно разберем все эффективные методы реализации этой задачи, проанализируем их плюсы и минусы, а также предоставим готовые листинги кода.

Способ 1. Использование встроенных средств 1С (Универсальный метод)

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

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


Процедура КопироватьПереместитьКаталог(СтарыйПуть, НовыйПуть, Переместить = Ложь) Экспорт
    
    // Проверим наличие завершающего слэша в пути назначения
    Если Прав(НовыйПуть, 1) <> "\" И Прав(НовыйПуть, 1) <> "/" Тогда
        НовыйПуть = НовыйПуть + "/";
    КонецЕсли;
    
    // Получаем имя исходного каталога, чтобы создать его внутри целевой папки
    ФайлИсточник = Новый Файл(СтарыйПуть);
    ИмяПапкиИсточника = ФайлИсточник.Имя;
    ПутьНазначенияСПапкой = НовыйПуть + ИмяПапкиИсточника;
    
    // Создаем корневой каталог в новом месте
    СоздатьКаталог(ПутьНазначенияСПапкой);
    
    // Ищем все файлы и подкаталоги рекурсивно (параметр Истина)
    НайденныеОбъекты = НайтиФайлы(СтарыйПуть, "*.*", Истина);
    
    Для Каждого Объект Из НайденныеОбъекты Цикл
        
        // Формируем новый путь путем замены старого префикса на новый
        НовыйПолныйПуть = СтрЗаменить(Объект.ПолноеИмя, СтарыйПуть, ПутьНазначенияСПапкой);
        
        Если Объект.ЭтоКаталог Тогда
            // Если это папка — просто создаем её
            СоздатьКаталог(НовыйПолныйПуть);
        Иначе
            // Перед копированием файла убедимся, что целевой каталог для него существует
            // Это важно, если дерево каталогов сложное
            ПапкаФайла = Новый Файл(НовыйПолныйПуть);
            Если НЕ Файл(ПапкаФайла.Путь).Существует() Тогда
                СоздатьКаталог(ПапкаФайла.Путь);
            КонецЕсли;
            
            Если Переместить Тогда
                ПереместитьФайл(Объект.ПолноеИмя, НовыйПолныйПуть);
            Иначе
                КопироватьФайл(Объект.ПолноеИмя, НовыйПолныйПуть);
            КонецЕсли;
        КонецЕсли;
        
    КонецЦикла;
    
    // Если была команда перемещения, удаляем исходный каталог в конце
    Если Переместить Тогда
        УдалитьФайлы(СтарыйПуть);
    КонецЕсли;

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

Проанализируем ситуацию: данный код использует параметр Истина в методе НайтиФайлы, что позволяет платформе самостоятельно выполнить глубокий поиск. Важный момент здесь — функция СтрЗаменить, которая "перебрасывает" файл из старой иерархии в новую. Этот метод работает одинаково хорошо как под Windows, так и под Linux.

Способ 2. Использование COM-объекта FileSystemObject (только для Windows)

Если решение разрабатывается исключительно под Windows и вам нужно написать минимум строк кода, можно воспользоваться объектом Scripting.FileSystemObject. Выясним причину его популярности: он позволяет копировать папки целиком одной командой.


Процедура СкопироватьПапкуЧерезFSO(ПутьИсточник, ПутьНазначение)
    Попытка
        FSO = Новый COMОбъект("Scripting.FileSystemObject");
        // Метод CopyFolder(Источник, Назначение, Перезаписывать)
        // Параметр Перезаписывать = Истина (True)
        FSO.CopyFolder(ПутьИсточник, ПутьНазначение, Истина);
    Исключение
        Сообщить("Ошибка при копировании: " + ОписаниеОшибки());
    КонецПопытки;
КонецПроцедуры

Важные нюансы: метод CopyFolder автоматически создает структуру папок. Однако стоит помнить, что этот метод не работает в веб-клиенте и на серверах под управлением Linux. Кроме того, при копировании заблокированных файлов может возникнуть ошибка, которую нужно обрабатывать блоком Попытка...Исключение.

Способ 3. Системные команды ОС (Robocopy и cp)

Для копирования очень больших объемов данных (терабайты файлов) или при необходимости зеркалирования папок лучше всего использовать специализированные системные утилиты. Рассмотрим пример использования robocopy, которая считается стандартом де-факто для Windows.

Разберем по шагам выполнение команды через 1С:

  1. Сформируем строку запуска.
  2. Используем метод ЗапуститьПриложение.
  3. Добавим ключи для копирования подпапок (/S или /E).

// Пример для Windows (Robocopy)
Команда = "robocopy """ + ИсходныйПуть + """ """ + ЦелевойПуть + """ /E /COPYALL /R:3 /W:5";
ЗапуститьПриложение(Команда,, Истина); // Ждем завершения (Истина)

// Пример для Linux
Команда = "cp -r " + ИсходныйПуть + " " + ЦелевойПуть;
ЗапуститьПриложение(Команда,, Истина);

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

Способ 4. "Хак" через ZIP-архив (Кроссплатформенный вариант)

Интересный и очень лаконичный способ скопировать всю папку со всеми вложенными элементами — использовать встроенные средства работы с архивами 1С. Платформа при упаковке и распаковке идеально сохраняет всю структуру подкаталогов.


Процедура КопироватьКаталогЧерезZip(Источник, Назначение)
    ВременныйФайл = ПолучитьИмяВременногоФайла("zip");
    
    // Запаковываем
    Архив = Новый ЗаписьZipФайла(ВременныйФайл);
    Архив.Добавить(Источник, РежимСохраненияПутейZIP.СохранятьОтносительныеПути);
    Архив.Записать();
    
    // Распаковываем в новое место
    Чтение = Новый ЧтениеZipФайла(ВременныйФайл);
    Чтение.ИзвлечьВсе(Назначение, РежимВосстановленияПутейФайловZIP.Восстанавливать);
    Чтение.Закрыть();
    
    УдалитьФайлы(ВременныйФайл);
КонецПроцедуры

Этот метод избавляет разработчика от написания рекурсии и ручного создания каждой вложенной папки. Платформа 1С берет всю рутину на себя.

Рекомендации по стабильности и производительности

При реализации копирования в реальных задачах, мы рекомендуем придерживаться следующих правил:

Выяснив все доступные методы, мы можем сделать вывод: для простых задач внутри Windows оптимален FileSystemObject, для кроссплатформенности и полного контроля — рекурсивный обход через НайтиФайлы, а для надежного бэкапа больших данных — вызов robocopy.

← На главную