В платформе 1С:Предприятие 7.7 работа с файловой системой реализована достаточно базово, и стандартный объект ФС (Файловая Система) не содержит прямой команды вроде «ПереместитьКаталог» или «КопироватьКаталог». Разработчики часто сталкиваются с трудностями, когда нужно перенести целую иерархию папок с файлами. В этой статье мы подробно разберем несколько способов решения этой задачи: от простого использования встроенных функций до применения мощных системных инструментов.
Многие программисты воспринимают функцию ПереименоватьФайл только как инструмент для смены имени конкретного файла. Однако в 1С 7.7 она обладает скрытой и очень полезной особенностью: эта функция способна работать с каталогами и выполнять их мгновенное перемещение.
Важное ограничение: этот метод работает корректно и мгновенно только в том случае, если исходная папка и папка назначения находятся на одном и том же логическом диске (например, внутри диска C:). В этом случае операционная система просто обновляет записи в файловой таблице, не переписывая данные физически.
Рассмотрим пример кода:
// Определяем пути
ПутьОткуда = "C:\MyFolder\SourceData";
ПутьКуда = "C:\Archives\OldData";
// Выполняем перемещение всей папки целиком
ФС.ПереименоватьФайл(ПутьОткуда, ПутьКуда, 1);
Здесь третий параметр 1 означает перезапись, если папка с таким именем уже существует. Если вам нужно именно переместить папку «по-простому», обязательно сначала попробуйте этот метод.
Если данные нужно перенести между разными дисками или сетевыми ресурсами, метод переименования не поможет. В такой ситуации нам придется реализовать алгоритм «обхода дерева», который будет заходить в каждую подпапку, создавать её копию в новом месте и копировать файлы по одному. Проанализируем пример кода, который часто используют разработчики, и выясним, почему он может выдавать ошибку.
Для начала нам понадобится вспомогательная функция, которая определяет, является ли найденный объект файлом или папкой. Мы будем использовать метод АтрибутыФайла:
Функция ЭтоКаталог(ИмяФайла)
Перем Размер, Атрибуты, Создан, Доступ, Запись, РасшИмяФайла;
Рез = 0;
ФС.АтрибутыФайла(ИмяФайла, Размер, Атрибуты, Создан, Доступ, Запись, РасшИмяФайла);
// В строке атрибутов 4-й символ "1" означает директорию
Если Сред(Атрибуты,4,1) = "1" Тогда
Рез = 1;
КонецЕсли;
Возврат Рез;
КонецФункции
Теперь разберем основную процедуру копирования. Обратите внимание, что мы используем рекурсию — функция вызывает саму себя для обработки вложенных папок:
Процедура КопироватьФайлы(ПутьОткуда, ПутьКуда)
ФС_ = СоздатьОбъект("ФС");
// Проверяем, существует ли целевая папка, если нет — создаем
Если (ФС_.СуществуетФайл(ПутьКуда) = 0) Тогда
ФС_.СоздатьКаталог(ПутьКуда);
КонецЕсли;
ИмяФайла = ФС_.НайтиПервыйФайл(ПутьОткуда + "\*.*");
Пока ПустаяСтрока(ИмяФайла) = 0 Цикл
// Игнорируем служебные записи "." и ".."
Если (ИмяФайла <> ".") И (ИмяФайла <> "..") Тогда
ПолныйПутьИсточника = ПутьОткуда + "\" + ИмяФайла;
ПолныйПутьПриемника = ПутьКуда + "\" + ИмяФайла;
Если ЭтоКаталог(ПолныйПутьИсточника) = 1 Тогда
// Если это папка, вызываем эту же процедуру (рекурсия)
КопироватьФайлы(ПолныйПутьИсточника, ПолныйПутьПриемника);
Иначе
// Если это файл, просто копируем его
ФС_.КопироватьФайл(ПолныйПутьИсточника, ПолныйПутьПриемника, 0);
КонецЕсли;
КонецЕсли;
ИмяФайла = ФС_.НайтиСледующийФайл();
КонецЦикла;
КонецПроцедуры
Часто после завершения копирования программист пытается вызвать ФС.УдалитьКаталог(ПутьОткуда), но получает ошибку «Ошибка при выполнении команды». Проанализируем причины этой ситуации:
УдалитьКаталог в 1С 7.7 работает только с абсолютно пустыми папками. Если вы просто скопировали файлы, оригиналы остались на месте. Чтобы удалить папку, вам нужно сначала удалить все файлы внутри неё с помощью ФС.УдалитьФайл(), причем делать это нужно также рекурсивно, начиная с самых глубоких уровней вложенности.Текст.Открыть(), папка считается занятой процессом 1С.Для «освобождения» папки используйте команду:
ФС.УстТекКаталог(КаталогИБ());
Если мы хотим избежать написания сложных рекурсивных функций и корректно обрабатывать удаление непустых папок, лучше всего воспользоваться мощностями операционной системы через COM-объект Scripting.FileSystemObject (FSO). Этот метод считается наиболее профессиональным для 1С 7.7.
Посмотрим на пример перемещения папки одной командой:
// Создаем объект для работы с файловой системой Windows
FSO = СоздатьОбъект("Scripting.FileSystemObject");
Попытка
// Метод MoveFolder сам перенесет всё дерево каталогов
FSO.MoveFolder("C:\SourcePath", "D:\DestinationPath");
Сообщить("Папка успешно перемещена!");
Исключение
Сообщить("Произошла ошибка: " + ОписаниеОшибки());
КонецПопытки;
Преимущества использования FSO:
MoveFolder автоматически обрабатывает вложенные структуры.DeleteFolder(Путь, 1) удаляет папку вместе со всем содержимым (параметр 1 принудительно удаляет даже файлы с атрибутом «Только для чтения»).Для задач, связанных с перемещением огромных массивов данных (гигабайты файлов), или при работе в нестабильных сетях, рекомендуется использовать встроенную утилиту Windows — Robocopy. Она умеет возобновлять копирование при разрывах связи и корректно переносит права доступа.
Разберем, как запустить её из 1С:
// /MOVE - переместить (удалить из источника после копирования)
// /E - копировать все подпапки (включая пустые)
Команда = "robocopy ""C:\Откуда"" ""D:\Куда"" /MOVE /E";
КомандаСистемы(Команда);
Подведем итог: если вам нужно быстро переименовать папку на том же диске — используйте ФС.ПереименоватьФайл. Если нужно надежное программное управление с минимумом кода — выбирайте Scripting.FileSystemObject. А если вы решите писать свой велосипед с рекурсией через ФС, не забудьте сначала очистить папку от файлов, прежде чем пытаться удалить сам каталог.