Имя, расширение и каталог из строки пути: разбор средствами 1С:Предприятия 8.3

· 10 мин

Содержание

Чтобы получить имя файла из полного пути в 1С, создайте объект Файл и прочитайте его свойство Имя: Новый Файл("C:\Выгрузка\Отчет.xlsx").Имя вернёт Отчет.xlsx. Свойства ИмяБезРасширения, Расширение и Путь дадут остальные части строки. Сам файл на диске для этого не нужен: платформа просто разбирает строку.

Объект Файл закрывает обычные задачи. Сбои начинаются, когда путь пришёл с другой операционной системы, строка оказалась URL с параметрами или путь заканчивается разделителем. Для таких строк надёжнее своя функция на строковых методах: она работает одинаково на клиенте и на сервере.

Чем платформа 1С помогает при работе с путями

В 1С:Предприятии 8.3 нет одной функции вида «ИмяФайлаИзПути()». Задачу решают тремя группами средств.

  • 📁 Объект Файл — разбирает полное имя файла на части и умеет проверять файл на диске.
  • 🔤 Строковые функции — СтрНайти, СтрРазделить, Сред, Лев, Прав, СтрДлина. Дают полный контроль над разбором.
  • 🧩 Библиотека стандартных подсистем (БСП) — в типовых конфигурациях есть готовая функция ОбщегоНазначенияКлиентСервер.РазложитьПолноеИмяФайла.

Рядом пригодятся служебные функции платформы:

ФункцияЧто возвращает
ПолучитьРазделительПути()Разделитель пути для ОС, где выполняется код: \ в Windows, / в Linux
ПолучитьРазделительПутиКлиента()Разделитель на компьютере пользователя
ПолучитьРазделительПутиСервера()Разделитель на сервере 1С
КаталогВременныхФайлов()Каталог временных файлов текущего сеанса
ПолучитьИмяВременногоФайла("xml")Полное имя уникального временного файла с заданным расширением

Разделитель не «зашивайте» в код как "\". Если база когда-нибудь переедет на сервер под Linux, код со склеиванием Каталог + "\" + Имя начнёт создавать файлы с обратной косой чертой в названии.

Из чего состоит полное имя файла

Возьмём строку C:\Обмен\2026\Выгрузка.данные.xml и посмотрим, как её видит платформа.

ЧастьСвойство объекта ФайлЗначение
Полное имяПолноеИмяC:\Обмен\2026\Выгрузка.данные.xml
КаталогПутьC:\Обмен\2026\
Имя с расширениемИмяВыгрузка.данные.xml
Имя без расширенияИмяБезРасширенияВыгрузка.данные
РасширениеРасширение.xml

Три детали, на которых чаще всего ошибаются:

  1. Расширение возвращается с точкой. .xml, а не xml. Сравнение Расширение = "xml" никогда не даст Истина.
  2. Путь заканчивается разделителем. Склеивать его с именем нужно без дополнительного \: Путь + Имя.
  3. Расширение — это всё после последней точки. У файла archive.tar.gz расширение .gz, а имя без расширения — archive.tar.

Регистр символов платформа не меняет. Если пользователь сохранил файл как ОТЧЕТ.XLSX, свойство Расширение вернёт .XLSX. Для проверок приводите строку к нижнему регистру через НРег().

Как извлечь имя файла в коде: рабочие примеры

Способ 1. Объект Файл

Самый короткий и читаемый вариант:

ПолноеИмяФайла = "C:\Обмен\2026\Выгрузка.данные.xml";
ФайлНаДиске = Новый Файл(ПолноеИмяФайла);

ИмяФайла         = ФайлНаДиске.Имя;              // Выгрузка.данные.xml
ИмяБезРасширения = ФайлНаДиске.ИмяБезРасширения; // Выгрузка.данные
Расширение       = ФайлНаДиске.Расширение;       // .xml
Каталог          = ФайлНаДиске.Путь;             // C:\Обмен\2026\

Проверка расширения без учёта регистра и без точки:

РасширениеБезТочки = НРег(Сред(ФайлНаДиске.Расширение, 2));
Если РасширениеБезТочки = "xml" Тогда
    // загружаем как XML
КонецЕсли;

Сред(Строка, 2) отрезает первый символ — точку. Если расширения нет, свойство вернёт пустую строку, и Сред тоже вернёт пустую строку, ошибки не будет.

Способ 2. Поиск последнего разделителя через СтрНайти

С платформы 8.3.6 у СтрНайти есть параметр направления поиска. Ищем последний разделитель с конца строки и берём всё, что после него. Функция учитывает оба разделителя, поэтому одинаково разбирает пути Windows и Linux на любой ОС.

Функция ИмяФайлаИзПути(Знач ПолноеИмяФайла) Экспорт

    ПолноеИмяФайла = СокрЛП(ПолноеИмяФайла);

    ПозицияОбратной = СтрНайти(ПолноеИмяФайла, "\", НаправлениеПоиска.СКонца);
    ПозицияПрямой   = СтрНайти(ПолноеИмяФайла, "/", НаправлениеПоиска.СКонца);
    ПозицияРазделителя = Макс(ПозицияОбратной, ПозицияПрямой);

    // Если разделителя нет, позиция 0 и вернётся вся строка
    Возврат Сред(ПолноеИмяФайла, ПозицияРазделителя + 1);

КонецФункции

Проверим на примерах:

Входная строкаРезультат
C:\Обмен\Выгрузка.xmlВыгрузка.xml
/home/usr1cv8/upload/price.csvprice.csv
\\srv-files\share\Акт.pdfАкт.pdf
Акт.pdfАкт.pdf
C:\Обмен\пустая строка

Последняя строка — это не ошибка функции, а честный ответ: в пути нет имени файла, это каталог.

Способ 3. Расширение и имя без расширения своими силами

Дополним функцию разбором по последней точке:

Функция РазобратьИмяФайла(Знач ПолноеИмяФайла) Экспорт

    Результат = Новый Структура("Каталог, Имя, ИмяБезРасширения, Расширение", "", "", "", "");

    ПолноеИмяФайла = СокрЛП(ПолноеИмяФайла);
    ПозицияРазделителя = Макс(
        СтрНайти(ПолноеИмяФайла, "\", НаправлениеПоиска.СКонца),
        СтрНайти(ПолноеИмяФайла, "/", НаправлениеПоиска.СКонца));

    Результат.Каталог = Лев(ПолноеИмяФайла, ПозицияРазделителя);
    Результат.Имя     = Сред(ПолноеИмяФайла, ПозицияРазделителя + 1);

    ПозицияТочки = СтрНайти(Результат.Имя, ".", НаправлениеПоиска.СКонца);
    Если ПозицияТочки > 1 Тогда
        Результат.ИмяБезРасширения = Лев(Результат.Имя, ПозицияТочки - 1);
        Результат.Расширение       = НРег(Сред(Результат.Имя, ПозицияТочки + 1));
    Иначе
        Результат.ИмяБезРасширения = Результат.Имя;
    КонецЕсли;

    Возврат Результат;

КонецФункции

Для C:\Обмен\Акт.сверки.PDF функция вернёт: каталог C:\Обмен\, имя Акт.сверки.PDF, имя без расширения Акт.сверки, расширение pdf — без точки и в нижнем регистре, как удобно для сравнений.

Условие ПозицияТочки > 1 отсекает имена, которые начинаются с точки, вроде .gitignore или .htaccess. Такую строку функция считает именем без расширения.

Способ 4. СтрРазделить — когда нужны все уровни пути

СтрРазделить режет строку по каждому символу из второго параметра. Передаём оба разделителя сразу:

Части = СтрРазделить("D:\Архив\2025\Декабрь\Реестр.xlsx", "\/", Ложь);
// Части[0] = "D:", Части[1] = "Архив", ..., Части[4] = "Реестр.xlsx"

Если Части.Количество() > 0 Тогда
    ИмяФайла = Части[Части.ВГраница()];
КонецЕсли;

Третий параметр Ложь выбрасывает пустые элементы. Из-за этого у пути с завершающим разделителем D:\Архив\2025\ последним элементом станет 2025 — имя последней папки. Это удобно, когда нужно именно имя каталога, и опасно, когда вы ждёте имя файла.

Способ 5. Платформа до 8.3.6 или старый режим совместимости

Если СтрНайти с направлением поиска недоступна, пройдите строку с конца циклом:

Функция ИмяФайлаИзПутиЦиклом(Знач ПолноеИмяФайла) Экспорт

    ДлинаСтроки = СтрДлина(ПолноеИмяФайла);

    Для Сч = 1 По ДлинаСтроки Цикл
        Позиция = ДлинаСтроки - Сч + 1;
        Символ  = Сред(ПолноеИмяФайла, Позиция, 1);
        Если Символ = "\" Или Символ = "/" Тогда
            Возврат Сред(ПолноеИмяФайла, Позиция + 1);
        КонецЕсли;
    КонецЦикла;

    Возврат ПолноеИмяФайла;

КонецФункции

Цикл идёт от последнего символа к первому и останавливается на первом встреченном разделителе. Строки путей короткие, так что по скорости разницы с СтрНайти вы не заметите.

Какой способ выбрать?

Получение имени файла на клиенте и на сервере

Объект Файл доступен и на клиенте, и на сервере. Но выполняется он там, где выполняется код, и разделитель берёт от этой ОС. Отсюда главная ловушка.

Сценарий: пользователь в Windows выбрал файл C:\Загрузка\Прайс.xlsx. Клиент передал строку на сервер, сервер работает под Linux. На сервере Новый Файл(Строка).Имя разбирает строку по правилам Linux, где \ — обычный символ, а не разделитель. Результат может оказаться не тем, что вы ждали.

Как избежать:

  • ✅ Разбирайте путь на клиенте, где он получен, и передавайте на сервер уже готовое имя файла.
  • ✅ Если разбор нужен на сервере — используйте функцию из способа 2, которая ищет оба разделителя.
  • ✅ Не передавайте на сервер путь клиента как место, откуда читать файл. Сервер не видит диск пользователя. Файл передают через временное хранилище, а имя — отдельным параметром.

Веб-клиент и выбор файла пользователем

В веб-клиенте браузер не отдаёт странице реальный путь к файлу на компьютере пользователя. Поэтому строим логику не на разборе полного пути, а на имени, которое возвращает платформа при помещении файла.

В актуальных версиях платформы метод ПоместитьФайлНаСерверАсинх возвращает ОписаниеПомещенногоФайла. У него есть свойство СсылкаНаФайл, а у неё — Имя и Расширение. Это и есть то, что нужно сохранить вместе с двоичными данными:

&НаКлиенте
Асинх Процедура ЗагрузитьФайл(Команда)

    Описание = Ждать ПоместитьФайлНаСерверАсинх(, , , , УникальныйИдентификатор);
    Если Описание = Неопределено Или Описание.ПомещениеФайлаОтменено Тогда
        Возврат;
    КонецЕсли;

    ИмяФайла = Описание.СсылкаНаФайл.Имя;
    ЗагрузитьНаСервере(Описание.Адрес, ИмяФайла);

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

Синхронные методы проверки файла на диске (Существует(), ЭтоФайл(), Размер()) в веб-клиенте без расширения работы с файлами не работают. Свойства Имя, Расширение, Путь к диску не обращаются, но для проверок в клиентском коде используйте асинхронные варианты: СуществуетАсинх(), ЭтоФайлАсинх().

Тонкий клиент и ДиалогВыбораФайла

В тонком клиенте диалог выбора отдаёт полный путь. Пример с асинхронным показом диалога:

&НаКлиенте
Асинх Процедура ВыбратьФайл(Команда)

    Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    Диалог.Фильтр = "Таблицы Excel (*.xlsx)|*.xlsx";

    ВыбранныеФайлы = Ждать Диалог.ВыбратьАсинх();
    Если ВыбранныеФайлы = Неопределено Тогда
        Возврат;
    КонецЕсли;

    Для Каждого ПолноеИмя Из ВыбранныеФайлы Цикл
        Сообщить(Новый Файл(ПолноеИмя).Имя);
    КонецЦикла;

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

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

Нестандартные строки и обработка ошибок разбора

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

Что встречается на практике:

  • 🔚 Путь заканчивается разделителем. C:\Обмен\ — это каталог. Перед разбором решите, что вам нужно: имя файла (тогда пустая строка — повод остановиться) или имя папки (тогда уберите завершающий разделитель и разбирайте снова).
  • ␣ Пробелы и переводы строк. Путь, скопированный из письма или ячейки Excel, часто несёт пробел или Символы.ПС в конце. СокрЛП() в начале функции снимает проблему.
  • 🔗 URL вместо пути. У строки https://site.ru/files/price.xlsx?v=3 имя файла — до вопросительного знака. Отрежьте параметры перед разбором.
  • 🔀 Смешанные разделители. C:/Обмен\Выгрузка.xml — функция из способа 2 справится, потому что ищет максимальную позицию из двух.
  • 📛 Недопустимые символы. Имя, полученное из внешней системы, может содержать :, *, ?, ", <, >, |. Windows такой файл не сохранит.

Отрезаем параметры URL:

ПозицияВопроса = СтрНайти(СтрокаАдреса, "?");
Если ПозицияВопроса > 0 Тогда
    СтрокаАдреса = Лев(СтрокаАдреса, ПозицияВопроса - 1);
КонецЕсли;
ИмяФайла = ИмяФайлаИзПути(СтрокаАдреса);

Чистим имя от запрещённых символов перед сохранением:

Функция БезопасноеИмяФайла(Знач ИмяФайла) Экспорт

    Запрещенные = "\/:*?""<>|";
    Для Сч = 1 По СтрДлина(Запрещенные) Цикл
        ИмяФайла = СтрЗаменить(ИмяФайла, Сред(Запрещенные, Сч, 1), "_");
    КонецЦикла;

    Возврат СокрЛП(ИмяФайла);

КонецФункции

Двойная кавычка внутри строки 1С записывается как "", поэтому в строке Запрещенные она одна, а в коде — две.

Проверку «имя не пустое» ставьте сразу после разбора: Если ПустаяСтрока(ИмяФайла) Тогда ... ВызватьИсключение .... Сообщение об ошибке со строкой исходного пути сэкономит время при разборе логов.

Альтернативы: БСП, НайтиФайлы и временные файлы

Готовая функция БСП

В типовых конфигурациях на Библиотеке стандартных подсистем (Бухгалтерия 3.0, ЗУП 3.1, УТ 11 и другие) есть функция ОбщегоНазначенияКлиентСервер.РазложитьПолноеИмяФайла. Она принимает полное имя и возвращает структуру с полями ПолноеИмя, Путь, Имя, Расширение, ИмяБезРасширения.

Части = ОбщегоНазначенияКлиентСервер.РазложитьПолноеИмяФайла(ПолноеИмяФайла);
ИмяФайла = Части.Имя;

Модуль клиент-серверный, так что вызов работает в любом контексте. Перед использованием откройте общий модуль в конфигураторе и посмотрите описание функции: состав параметров и формат расширения (с точкой или без) лучше проверить по своей версии БСП, а не по памяти.

НайтиФайлы: имена уже готовы

Если имена нужны для файлов из каталога, разбирать строки не придётся. НайтиФайлы возвращает массив объектов Файл, у каждого уже есть Имя и Расширение:

Найденные = НайтиФайлы("C:\Обмен\Входящие", "*.xml", Ложь);
Для Каждого НайденныйФайл Из Найденные Цикл
    Сообщить(НайденныйФайл.Имя + " — " + НайденныйФайл.Путь);
КонецЦикла;

Третий параметр Ложь означает поиск без подкаталогов. Передайте Истина, чтобы обойти вложенные папки.

Временные файлы

ПолучитьИмяВременногоФайла("xlsx") возвращает полное имя в каталоге временных файлов. Если нужно только сгенерированное имя — например, чтобы записать его в журнал, — примените к результату любой способ выше. Сами временные файлы после работы удаляйте через УдалитьФайлы(), иначе они копятся на сервере.

Сравнение способов

СпособКогда подходитОграничения
Объект ФайлПуть получен на той же машинеРазделитель берётся от ОС, где выполняется код
СтрНайти с концаПути из обменов, писем, с другого сервераПлатформа 8.3.6 и новее
СтрРазделитьНужны все уровни пути или имя папкиЗавершающий разделитель даёт имя каталога, а не файла
Функция БСПТиповая конфигурацияНет в нетиповых базах без БСП
Цикл через СредСтарые платформы и режимы совместимостиБольше кода
НайтиФайлыРабота с содержимым каталогаТолько для файлов, которые реально есть на диске

Частые ошибки разработчиков

  • ❌ Сравнивают расширение без точки с результатом Файл.Расширение. Свойство возвращает .pdf. Либо сравнивайте с точкой, либо отрежьте её через Сред(…, 2).
  • ❌ Считают расширением всё после первой точки. Для Счет.от.01.10.pdf поиск первой точки даст «расширение» от.01.10.pdf. Ищите последнюю точку.
  • ❌ Хранят только полный путь клиента в реквизите документа. Через месяц файл переедет, и путь станет бесполезным. Сохраняйте имя файла отдельным реквизитом, а сам файл — в присоединённых файлах или хранилище значения.
  • ❌ Восстанавливают имя из ДвоичныеДанные. Двоичные данные хранят только содержимое. Имя теряется в момент помещения во временное хранилище, если не передать его рядом.

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

Как получить имя каталога информационной базы?
Для файловой базы вызовите СтрокаСоединенияИнформационнойБазы(). Она вернёт строку вида File="C:\Базы\Бухгалтерия";. Значение между кавычками после File= и есть каталог базы. Для клиент-серверной базы в строке будут Srvr и Ref — имя сервера и имя базы на нём.
Как получить имя последней папки в пути?
Уберите завершающий разделитель, если он есть, и примените к строке ту же функцию, что для имени файла. Либо используйте СтрРазделить(Путь, "\/", Ложь) и возьмите последний элемент массива.
Обращается ли Новый Файл к диску при чтении свойства Имя?
Нет. Свойства Имя, ИмяБезРасширения, Расширение, Путь вычисляются из строки. Файла может не быть вовсе. К диску обращаются методы Существует(), Размер(), ПолучитьВремяИзменения() и их асинхронные варианты.
Как собрать полный путь обратно из каталога и имени?
Если каталог получен из Файл.Путь, он уже заканчивается разделителем: Каталог + ИмяФайла. Если каталог пришёл из настроек, проверьте последний символ через Прав(Каталог, 1) и при необходимости добавьте ПолучитьРазделительПути().
Можно ли получить имя файла, который пользователь перетащил на форму?
Да. В обработчике перетаскивания значение лежит в ПараметрыПеретаскивания.Значение. Проверьте его тип в отладчике: для файлов это объект с собственным свойством Имя или массив таких объектов. Читайте имя из свойства, а не разбирайте строку.