Полный путь на входе, имя на выходе: разбор строки пути средствами встроенного языка 1С
Содержание
Чтобы получить имя файла из пути в 1С 8.3, создайте объект Файл и прочитайте его свойство Имя: Новый Файл("C:\Выгрузки\Отчет.xlsx").Имя вернёт Отчет.xlsx. Свойство ИмяБезРасширения даст Отчет, Расширение — .xlsx с точкой, Путь — C:\Выгрузки\ с разделителем на конце. Сам файл при этом может и не существовать: объект разбирает строку, а на диск идёт только при вызове Существует() и подобных методов.
Отдельной глобальной функции «ИмяФайла» во встроенном языке нет. Если объект Файл не подходит (строка пришла с другой ОС, путь собран вручную, код работает в веб-клиенте), имя вырезают функциями работы со строками. Оба способа, работа с расширением, сетевые пути и очистка имени — ниже, с готовым кодом.
Объект Файл: самый короткий способ получить имя из полного пути
Объект Файл доступен на клиенте и на сервере. Конструктор принимает строку с полным именем. Всё, что нужно для разбора пути, лежит в его свойствах.
ПолныйПуть = "D:\Обмен\Банк\kl_to_1c.txt";
ФайлОбъект = Новый Файл(ПолныйПуть);
Сообщить(ФайлОбъект.Имя); // kl_to_1c.txt
Сообщить(ФайлОбъект.ИмяБезРасширения); // kl_to_1c
Сообщить(ФайлОбъект.Расширение); // .txt
Сообщить(ФайлОбъект.Путь); // D:\Обмен\Банк\
Сообщить(ФайлОбъект.ПолноеИмя); // D:\Обмен\Банк\kl_to_1c.txt
Что вернёт каждое свойство:
| Свойство | Что содержит | Пример для D:\Обмен\Банк\kl_to_1c.txt |
|---|---|---|
Имя | имя с расширением | kl_to_1c.txt |
ИмяБезРасширения | имя без последней точки и хвоста | kl_to_1c |
Расширение | расширение с точкой | .txt |
Путь | каталог с разделителем на конце | D:\Обмен\Банк\ |
ПолноеИмя | исходная строка целиком | D:\Обмен\Банк\kl_to_1c.txt |
Обёртка, которую удобно положить в общий модуль с флажками «Клиент» и «Сервер»:
Функция ИмяФайлаПоПути(Знач ПолныйПуть) Экспорт
Если ПустаяСтрока(ПолныйПуть) Тогда
Возврат "";
КонецЕсли;
Возврат (Новый Файл(СокрЛП(ПолныйПуть))).Имя;
КонецФункции
СокрЛП здесь не лишний. Пути часто приходят из реквизитов, ячеек Excel или текстовых файлов с пробелом или переводом строки в конце. Без обрезки такой хвост попадёт в имя, и сравнение Имя = "kl_to_1c.txt" не сработает.
Если в конфигурации есть Библиотека стандартных подсистем, посмотрите функцию ОбщегоНазначенияКлиентСервер.РазложитьПолноеИмяФайла. Она возвращает структуру с полями ПолноеИмя, Путь, Имя, Расширение, ИмяБезРасширения и работает без объекта Файл. Перед использованием откройте её описание в общем модуле: состав параметров зависит от версии БСП.
Где объект Файл подводит
- 🐧 Сервер на Linux, путь из Windows. Разделитель на Linux —
/. Обратную косую черту объект там не считает разделителем, иНовый Файл("C:\Папка\Счет.pdf").Имявернёт всю строку целиком. - 🌐 Веб-клиент. Объект
Файлтам есть, но работа с локальной файловой системой ограничена браузером, а полный путь пользователь часто вообще не передаёт. - 🔗 URL и пути из внешних систем. Строки вида
https://site.ru/files/act.pdf?id=5объект разберёт по-своему, параметры после?останутся в имени.
В этих случаях надёжнее ручной разбор строки.
Ручной разбор пути через поиск последнего разделителя
Логика простая: найти последний разделитель каталогов и взять всё, что правее. В платформе 8.3.6 и выше для этого есть СтрНайти с поиском с конца строки.
Функция ИмяФайлаИзСтроки(Знач ПолныйПуть) Экспорт
Путь = СокрЛП(ПолныйПуть);
// Приводим оба вида разделителей к одному
Путь = СтрЗаменить(Путь, "/", "\");
// Срезаем разделители на конце: "C:\Папка\" -> "C:\Папка"
Пока СтрЗаканчиваетсяНа(Путь, "\") Цикл
Путь = Лев(Путь, СтрДлина(Путь) - 1);
КонецЦикла;
Позиция = СтрНайти(Путь, "\", НаправлениеПоиска.СКонца);
Если Позиция = 0 Тогда
Возврат Путь; // разделителей нет, строка и есть имя
КонецЕсли;
Возврат Сред(Путь, Позиция + 1);
КонецФункции
Прогоним функцию на примерах:
| Входная строка | Результат |
|---|---|
C:\Docs\Акт 15.pdf | Акт 15.pdf |
/home/user1c/exchange/orders.xml | orders.xml |
D:\Обмен\Банк\ | Банк |
Прайс.xlsx | Прайс.xlsx |
| пустая строка | пустая строка |
Строка с разделителем на конце — это путь к каталогу. Функция вернёт имя последней папки. Если вам нужно, чтобы для каталога возвращалась пустая строка, уберите цикл с СтрЗаканчиваетсяНа.
Вариант через СтрРазделить
Короче получается с СтрРазделить. Вторым параметром можно передать сразу несколько символов: каждый из них считается разделителем.
Части = СтрРазделить(СокрЛП(ПолныйПуть), "\/", Ложь);
ИмяФайла = ?(Части.Количество() = 0, "", Части[Части.ВГраница()]);
Третий параметр Ложь выбрасывает пустые элементы. Благодаря ему двойные разделители и косая черта на конце не дают пустого результата. Проверка Количество() = 0 нужна для пустой входной строки, иначе обращение к индексу -1 вызовет ошибку.
Для старых платформ: цикл с Найти
СтрНайти, СтрРазделить и СтрЗаканчиваетсяНа появились в 8.3.6. В конфигурациях, запущенных в режиме совместимости с более ранней версией, этих функций нет. Тогда работает старый приём с Найти, которая ищет только с начала строки:
Путь = СтрЗаменить(СокрЛП(ПолныйПуть), "/", "\");
Позиция = Найти(Путь, "\");
Пока Позиция > 0 Цикл
Путь = Сред(Путь, Позиция + 1);
Позиция = Найти(Путь, "\");
КонецЦикла;
ИмяФайла = Путь;
Каждый проход отрезает путь до очередного разделителя. Когда разделителей не осталось, в переменной лежит имя.
Какой способ выбрать
| Способ | Когда подходит | Ограничения |
|---|---|---|
Новый Файл(...).Имя | путь локальный, формат совпадает с ОС, где выполняется код | на Linux не понимает \ |
СтрНайти с конца | любые строки, нужен контроль над разделителями | платформа 8.3.6+, без режима совместимости |
СтрРазделить | короткий код, смешанные разделители | платформа 8.3.6+ |
Цикл с Найти | старые конфигурации в режиме совместимости | длиннее, медленнее на очень длинных строках |
РазложитьПолноеИмяФайла из БСП | в конфигурации есть БСП | зависит от версии библиотеки |
Имя без расширения и работа с расширением файла
Расширение — всё после последней точки в имени. Ключевое слово здесь «в имени», а не «в пути». Сначала выделите имя, потом ищите точку.
Почему это важно: в пути C:\Отчеты.2025\Выписка точка стоит в имени папки. Если искать её по всей строке, получите «расширение» .2025\Выписка. Объект Файл эту ловушку обходит сам, ручной код — нет.
Функция РазделитьИмяИРасширение(Знач ИмяФайла) Экспорт
Результат = Новый Структура("ИмяБезРасширения, Расширение", ИмяФайла, "");
Позиция = СтрНайти(ИмяФайла, ".", НаправлениеПоиска.СКонца);
// Позиция = 1 — имя начинается с точки, расширения нет
Если Позиция > 1 Тогда
Результат.ИмяБезРасширения = Лев(ИмяФайла, Позиция - 1);
Результат.Расширение = Сред(ИмяФайла, Позиция); // с точкой
КонецЕсли;
Возврат Результат;
КонецФункции
Для Реестр.платежей.xml функция вернёт имя Реестр.платежей и расширение .xml. Для backup.tar.gz расширением считается только .gz. Если нужно распознавать составные расширения, проверяйте их отдельно через СтрЗаканчиваетсяНа.
Проверка типа файла по расширению
Сравнивайте расширение без учёта регистра. Пользователи присылают и .XLSX, и .Xlsx.
Расширение = НРег((Новый Файл(ПолныйПуть)).Расширение);
Если Расширение = ".xlsx" Или Расширение = ".xls" Тогда
// загрузка из Excel
КонецЕсли;
Замена расширения
Типичная задача — сохранить рядом с исходным файлом его копию в другом формате:
ФайлОбъект = Новый Файл(ПолныйПуть);
НовоеИмя = ФайлОбъект.Путь + ФайлОбъект.ИмяБезРасширения + ".pdf";
Свойство Путь уже содержит разделитель на конце, добавлять его второй раз не нужно.
Сетевые пути UNC и пути на разных ОС
Сетевой путь Windows выглядит так: \\fileserver\obmen\2025\выписка.txt. Два разделителя в начале, затем имя сервера и общая папка. Для извлечения имени файла это обычный путь: последний \ стоит перед выписка.txt, и оба способа выше дают правильный ответ.
Сложности начинаются в другом месте.
- 🖥️ Код выполняется на сервере 1С. Путь
\\fileserver\obmen\...должен быть доступен учётной записи, под которой работает служба сервера 1С, а не пользователю за компьютером. Для разбора строки это неважно, для чтения файла — критично. - 🐧 Сервер 1С на Linux. UNC-пути Windows там не работают. Сетевая папка монтируется в каталог вроде
/mnt/obmen, и путь в коде нужно строить уже от него. - 🔀 Смешанные разделители. Пути, склеенные в коде, нередко выглядят так:
\\server\share/folder/file.xml. Перед разбором приведите разделители к одному виду черезСтрЗаменить.
Разделитель текущей ОС
Чтобы не зашивать \ или / в код, берите разделитель у платформы:
Разделитель = ПолучитьРазделительПути();
Есть ещё ПолучитьРазделительПутиКлиента() и ПолучитьРазделительПутиСервера(). Они нужны, когда путь формируется на клиенте под Windows, а обрабатывается на сервере под Linux или наоборот.
Путь из диалога выбора файла
Полный путь после ДиалогВыбораФайла лежит в свойстве ПолноеИмяФайла. Имя из него получают тем же объектом Файл прямо на клиенте. В веб-клиенте браузер обычно не отдаёт настоящий путь к файлу на компьютере пользователя: строите логику на имени, а не на каталоге.
\ на / или разбирайте строку вручную через СтрРазделить с обоими разделителями.Как очистить имя файла от недопустимых символов
Обратная задача: имя собирают из данных 1С и сохраняют файл на диск. Например, Акт № 15/3 от 01.10 "Ромашка".pdf. Косая черта и кавычки в Windows запрещены, и ЗаписатьФайл упадёт с ошибкой.
Символы, которые Windows не принимает в имени файла:
| Символ | Где встречается в данных 1С |
|---|---|
\ / | номера документов вида 15/3, ИНН/КПП через косую черту |
: | время в строковых датах, ООО: Ромашка |
* ? | маски, вопросы в комментариях |
" | наименования организаций в кавычках |
< > | | редко, но бывают в комментариях |
Кроме того, Windows не принимает имена CON, PRN, AUX, NUL, COM1–COM9, LPT1–LPT9 (с любым расширением) и обрезает точки и пробелы в конце имени.
Функция очистки:
Функция БезопасноеИмяФайла(Знач Имя, Знач Замена = "_") Экспорт
Недопустимые = "\/:*?""<>|";
Для Сч = 1 По СтрДлина(Недопустимые) Цикл
Имя = СтрЗаменить(Имя, Сред(Недопустимые, Сч, 1), Замена);
КонецЦикла;
// Табуляции и переводы строк из многострочных реквизитов
Имя = СтрЗаменить(Имя, Символы.Таб, " ");
Имя = СтрЗаменить(Имя, Символы.ПС, " ");
Имя = СтрЗаменить(Имя, Символы.ВК, " ");
Имя = СокрЛП(Имя);
// Точки на конце Windows отбросит сама, убираем их явно
Пока СтрЗаканчиваетсяНа(Имя, ".") Цикл
Имя = Лев(Имя, СтрДлина(Имя) - 1);
КонецЦикла;
Возврат ?(ПустаяСтрока(Имя), "file", Имя);
КонецФункции
Кавычка внутри строкового литерала во встроенном языке удваивается, поэтому в строке "\/:*?""<>|" она записана как "". Всего в строке девять символов, цикл заменит каждый.
Применяйте функцию к имени без расширения, а расширение добавляйте после:
ИмяФайла = БезопасноеИмяФайла("Акт № 15/3 ""Ромашка""") + ".pdf";
// Акт № 15_3 _Ромашка_.pdf
В БСП для этой задачи есть ОбщегоНазначенияКлиентСервер.ЗаменитьНедопустимыеСимволыВИмениФайла. Если библиотека в конфигурации есть, лучше вызывать её, чем держать свою копию.
Длина пути
Классическое ограничение Windows — 260 символов на полный путь. Длинные наименования номенклатуры плюс глубокая структура папок упираются в него быстро. Обрезайте имя через Лев(Имя, 100) до добавления расширения, если оно строится из наименований.
Отладка разбора пути: на что смотреть
Ошибки разбора пути редко ломают программу сразу. Обычно файл сохраняется «не туда» или загрузка молча пропускает строку. Что проверять в отладчике.
- Смотрите строку посимвольно. Поставьте точку останова и выведите
СтрДлина(Путь). Если длина на 1–2 символа больше видимой, в конце сидит пробел,Символы.ПСилиСимволы.ВК. - Проверяйте, где выполняется код. Директива
&НаСервереу процедуры означает, что разделитель и права определяет сервер. Клиентская машина под Windows и сервер под Linux дают разный результат одной и той же строки кода. - Не путайте имя и существование.
Новый Файл(Путь).Имявернёт имя даже для несуществующего файла. Если дальше файл читается, проверяйтеФайлОбъект.Существует()до чтения. - Логируйте исходную строку. При загрузке из внешних систем запишите сырой путь в журнал регистрации через
ЗаписьЖурналаРегистрации. Часто ответ виден сразу по тому, что реально пришло. - Отделяйте параметры URL. Для ссылок вида
.../act.pdf?id=5&token=...сначала отрежьте всё после?, потом выделяйте имя.
Фрагмент для URL:
Позиция = СтрНайти(Адрес, "?");
Если Позиция > 0 Тогда
Адрес = Лев(Адрес, Позиция - 1);
КонецЕсли;
ИмяФайла = ИмяФайлаИзСтроки(Адрес);
Здесь используется функция ИмяФайлаИзСтроки из раздела про ручной разбор: она уже приводит / к \ и берёт хвост после последнего разделителя.
Частые вопросы
Почему свойство Расширение возвращает значение с точкой?
.xlsx, а не xlsx. При сравнении пишите точку в образце или отрежьте её через Сред(Расширение, 2).Можно ли получить имя файла в запросе 1С?
Как получить имя последней папки в пути?
D:\Обмен\Банк\ получится Банк. У объекта Файл для этого подойдёт Новый Файл(СокрЛП(Путь)).Имя для строки без разделителя на конце.Чем отличаются свойства Имя и ПолноеИмя?
Имя — только имя с расширением. ПолноеИмя — исходная строка с каталогом, то есть то, что вы передали в конструктор.Нужно ли, чтобы файл существовал, для получения его имени?
Существует().