Синтаксис шаблона

Обновлено 5 ноября 2026

Шаблон — это обычный конфигурационный файл. Его первая строка может быть служебной: она начинается с # Calculate и описывает, как переносить содержимое в систему. Из неё три вещи: параметры (format=…, path=…), условия (ac_install_merge==on) и подстановки внутри значений (#-переменная-#).

# Calculate format=samba name=smb.conf path=/etc [параметры] [условия && условия]

Заголовок можно переносить на несколько строк: если первая начинается с # Calculate и заканчивается одинарным \, продолжением считается следующая строка. Продолжение без # применяется, строка продолжения, начинающаяся с #, приводит к Неправильный шаблон, а два подряд \ ломают разбор.

Служебная строка не обязательна. Без заголовка шаблон трактуется как «сырой» файл: он полностью перезапишет цель (format=raw, следствие — append=replace), а путь возьмётся из текущего положения — от корня хранилища, продолжая директории, которые идут выше по дереву шаблонов. Практическое следствие: если вы кладёте файл без заголовка в поддиректорию, её имя попадёт в путь результата, а переменная действия при этом обязана быть в заголовке элемента первого уровня — иначе поддерево молча пропустится.

Параметры заголовка файла

параметр значение
format= формат конфигурационного файла: kde, samba, openrc, procmail, xml_xfce, json, patch, diff, kernel, dconf, world, contents, sqlite, backgrounds, plasma и др. Без него — raw. Список и различия →
comment= символ комментария целевого файла (#, ;, --); специальное значение xml/XML включает парные <!-- -->
append= способ объединения: join, before, after, replace, remove, skip, patch, clear
path= директория, где окажется конфигурационный файл
name= имя конфигурационного файла (по умолчанию — имя файла шаблона)
link= файл, из которого берётся текст шаблона (сам шаблон при этом не читается); с symbolic — цель создаваемой ссылки
symbolic создать символическую ссылку на файл из link=
mirror налагать только если конфигурационный файл существует; если он задан link= и такого файла нет, файл назначения удаляется
force удалять существующий файл перед записью (включено автоматически при symbolic)
protected не удалять файл при удалении пакета, которому он принадлежит
chmod= права на результат
chown= владелец и группа (user:group)
autoupdate после наложения перенести изменённый конфиг в систему без dispatch-conf
run= оболочка для выполнения результата сразу после обработки шаблона
exec= то же, но скрипт ставится в очередь после всех обычных шаблонов
env= модуль переменных (install, desktop, update, …); если модуль недоступен — шаблон пропускается
module= имя модуля шаблонов
merge= в конце настроить перечисленные пакеты (sys-apps/openrc,sys-boot/grub)
postmerge= то же, но после pkg_postinst() при сборке пакета
rebuild= понизить версию пакета для пересборки при обновлении системы
restart=, start=, stop= перезапустить/запустить/остановить перечисленные через запятую сервисы
multiline, dotall режимы работы регулярных выражений; читаются только форматом patch
stretch, convert, dconf параметры форматов backgrounds и dconf

Недопустимый параметр в заголовке — ошибка: утилита сообщит incorrect header parameter: '<имя>' и пропустит шаблон.

Параметры заголовка директории

Директория-шаблон описывается файлом .calculate_directory в ней. Набор параметров другой и он заметно короче:

append=, path=, name=, link= (копирует содержимое директории), chmod=, chown=, mirror, subvolume (создать как btrfs-подтом), autoupdate, env=, module=, merge=, postmerge=, rebuild=, restart=, start=, stop=.

Здесь нет format=, comment=, symbolic, protected, force, run=, exec=, multiline, dotall — они относятся к файлу.

Для директории допустимы только append=join|remove|skip|clear, а link= сочетается лишь с append=join или append=replace.

Директория без .calculate_directory — не ошибка: она просто переносится в систему как есть. Если вы этого не хотите, создайте в ней файл .calculate_directory с одной строкой заголовка:

.calculate_directory

# Calculate append=skip

Иначе в системе появится лишняя директория (проверить заранее можно офлайн-наложением).

Значения по умолчанию, о которых полезно знать

Если в заголовке нет append=, он выбирается по формату:

  • patch и «исполняемые» форматы (diff, dconf, contents, sqlite, backgrounds) → patch; более того, для них append= обязан быть patch: другое значение утилита отвергнет с сообщением Wrong option 'append=<значение>' in template <файл>;
  • любой другой формат → join (объединение);
  • raw, bin → replace (полная запись).

name= по умолчанию берётся из имени файла шаблона, path= — из родительской директории шаблона или наследуется от .calculate_directory.

Переменные и функции

Подстановка значения переменной — #-имя-#, из другого модуля — #-модуль.имя-#:

HOSTNAME="#-os_net_hostname-#"
Modes "#-install.os_install_x11_resolution-#"

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

  • pkg(cat/pkg), merge(cat/pkg), mergepkg(cat/pkg) — про установленный/настраиваемый пакет. mergepkg() — это «настраивается именно этот пакет» и «пакет установлен»: версия берётся из базы /var/db/pkg. Если список настраиваемых пакетов пуст, merge() даёт истину;
  • exists(путь[,root]) — существует ли файл/директория; вместо 1 возвращает тип (f, d, l, …), поэтому условие обычно пишут как exists(/etc/x)!=;
  • ini(секция.ключ) — читает переменную из стека ini.env;
  • grep(файл, регулярное) — первое совпадение из файла;
  • cut(номер[разделитель[строка]]) — фрагмент строки; по умолчанию разделитель -, а строка берётся из cl_pass_file — имени обрабатываемого файла шаблона (для директории — её имени). Нумерация полей с нуля: cut(0,-,a-b-c) → a, cut(1,-,a-b-c) → b, cut(2,-,a-b-c) → c; номер за концом строки даёт пустое значение, отрицательный — ошибку шаблона (cut(-1,-,a-b-c) обрывает шаблон с ошибка в шаблоне);
  • in(переменная,значения…), groups(группы…), ls(каталог,шаблон), env(модуль.переменная), case(тип,переменная), list(переменная,индекс), sum(), push()/pop() (стек между шаблонами).

Переменные функций можно создавать и менять внутри шаблона; их область — текущий шаблон, а через push()/pop() значение передаётся в другой.

Условия в заголовке

Условия идут после параметров в той же строке. Операторы: >, <, ==, !=, >=, <=, а для версий также <> (вне интервала) и =>, <= (границы интервала, задаваемого через запятую).

  • несколько условий через пробел объединяются «И»;
  • явные связки: && («И»), || («ИЛИ»), приоритет у «И»;
  • пустая правая часть (!=, ==) означает «значение непустое» / «значение пустое».
# Calculate cl_ver>=3.5 os_linux_shortname==CLDX||os_linux_shortname==CLD

читается как «версия ≥ 3.5 и (CLDX или CLD)».

Левая часть условия может быть вызовом функции без обрамления: exists(/etc/f)==, ini(x.y)!=off, checkdev(wan0)!=.

Условные блоки в теле

Блок текста подставляется, если условие истинно. Начало — #?условие# в начале строки, конец — #имя_первой_переменной_условия#:

#?os_locale_language==ru&&pkg(media-gfx/cldx-themes)!=#
current_theme calculate_ru
#os_locale_language#

Внутри блока, как и везде, доступны подстановки #-…-#; переменные вычисляются раньше функций, поэтому в аргумент функции можно передать #-переменную-#.

Как менять, добавлять и удалять записи

Способ зависит от формата, но базовый набор префиксов имён такой:

  • ключ=значение — установить значение (добавить, если ключа не было);
  • !ключ= — удалить ключ; работает во всех ini-подобных форматах (samba, kde, openrc, procmail, postfix, …);
  • +ключ=значение — добавить значение к разделяемому списку (samba, ldap);
  • -ключ=значение — формально означает «заменить», но действия за ним не стоит: код префикс - действия не выставляет, и поведение сводится к обычной записи. В kde дела хуже: +/- на уровне ключа не распознаются вовсе и остаются внутри имени, так что +key= создаст параметр с именем +key, который никогда не совпадёт с key. В kde удаляйте только через !.

На уровне секции ! перед именем группы удаляет её, - — заменяет целиком.

См. также