26.9.4 Функции, которые раскрывают имена файлов

Раскрытие имени файла означает преобразование относительного имени файла в абсолютное. Поскольку это делается относительно каталога по умолчанию, вы должны указать как каталог по умолчанию, так и имя файла, которое нужно раскрыть. Это также включает раскрытие сокращений, таких как ~/ (см. abbreviate-file-name), и устранение избыточностей, таких как ./ и имя/../.

Функция: expand-file-name filename &optional directory

Эта функция преобразует filename в абсолютное имя файла. Если указан directory, он является каталогом по умолчанию, с которого начинается, если filename является относительным и не начинается с ‘~’. (Значение directory должно само быть абсолютным именем каталога или именем файла-каталога; оно может начинаться с ‘~’.) В противном случае используется значение default-directory текущего буфера. Например:

(expand-file-name "foo")
     ⇒ "/xcssun/users/rms/lewis/foo"
(expand-file-name "../foo")
     ⇒ "/xcssun/users/rms/foo"
(expand-file-name "foo" "/usr/spool/")
     ⇒ "/usr/spool/foo"

Если часть filename перед первой косой чертой — это ‘~’, она раскрывается в ваш домашний каталог, который обычно задаётся значением переменной окружения HOME (см. Общие переменные в Руководстве по GNU Emacs). Если часть перед первой косой чертой — это ‘~user’ и если user является допустимым именем для входа, она раскрывается в домашний каталог user. Если вы не хотите такого раскрытия для относительного filename, который может начинаться с буквального ‘~’, вы можете использовать (concat (file-name-as-directory directory) filename) вместо (expand-file-name filename directory).

Имена файлов, содержащие ‘.’ или ‘..’, упрощаются до их канонической формы:

(expand-file-name "bar/../foo")
     ⇒ "/xcssun/users/rms/lewis/foo"

В некоторых случаях ведущий компонент ‘..’ может остаться в выводе:

(expand-file-name "../home" "/")
     ⇒ "/../home"

Это сделано ради файловых систем, в которых существует понятие супер-корня над корневым каталогом /. В других файловых системах /../ интерпретируется точно так же, как /.

Раскрытие . или пустой строки возвращает каталог по умолчанию:

(expand-file-name "." "/usr/spool/")
     ⇒ "/usr/spool"
(expand-file-name "" "/usr/spool/")
     ⇒ "/usr/spool"

Обратите внимание, что expand-file-name не раскрывает переменные окружения; это делает только substitute-in-file-name:

(expand-file-name "$HOME/foo")
     ⇒ "/xcssun/users/rms/lewis/$HOME/foo"

Также обратите внимание, что expand-file-name не переходит по символическим ссылкам на любом уровне. Это приводит к различию между тем, как file-truename и expand-file-name обрабатывают ‘..’. Предполагая, что ‘/tmp/bar’ является символической ссылкой на каталог ‘/tmp/foo/bar’, получаем:

(file-truename "/tmp/bar/../myfile")
     ⇒ "/tmp/foo/myfile"
(expand-file-name "/tmp/bar/../myfile")
     ⇒ "/tmp/myfile"

Если вам может понадобиться переходить по символическим ссылкам, предшествующим ‘..’, вам следует вызывать file-truename без предварительных прямых или косвенных вызовов expand-file-name. См. Истинные имена.

Переменная: default-directory

Значение этой буферно-локальной переменной является каталогом по умолчанию для текущего буфера. Оно должно быть абсолютным именем каталога; может начинаться с ‘~’. Эта переменная является буферно-локальной в каждом буфере.

expand-file-name использует каталог по умолчанию, когда его второй аргумент равен nil.

Значение всегда является строкой, оканчивающейся косой чертой.

default-directory
     ⇒ "/user/lewis/manual/"
Функция: substitute-in-file-name filename

Эта функция заменяет ссылки на переменные окружения в filename значениями переменных окружения. Следуя стандартному синтаксису Unix-оболочки, ‘$’ является префиксом для подстановки значения переменной окружения. Если входное значение содержит ‘$$’, оно преобразуется в ‘$’; это даёт пользователю способ экранировать ‘$’.

Имя переменной окружения — это последовательность буквенно-цифровых символов (включая символы подчёркивания), следующих за ‘$’. Если символ после ‘$’ — это ‘{’, то именем переменной является всё до соответствующей ‘}’.

Вызов substitute-in-file-name для вывода, полученного от substitute-in-file-name, как правило, даёт неверные результаты. Например, использование ‘$$’ для экранирования одного ‘$’ не будет работать должным образом, а ‘$’ в значении переменной окружения может привести к повторной подстановке. Поэтому программы, которые вызывают эту функцию и помещают вывод туда, где он будет передан этой функции, должны удваивать все символы ‘$’, чтобы предотвратить последующие неверные результаты.

Здесь мы предполагаем, что переменная окружения HOME, которая содержит домашний каталог пользователя, имеет значение ‘/xcssun/users/rms’.

(substitute-in-file-name "$HOME/foo")
     ⇒ "/xcssun/users/rms/foo"

После подстановки, если ‘~’ или ‘/’ появляется непосредственно после другого ‘/’, функция отбрасывает всё перед ним (включая непосредственно предшествующий ‘/’).

(substitute-in-file-name "bar/~/foo")
     ⇒ "~/foo"
(substitute-in-file-name "/usr/local/$HOME/foo")
     ⇒ "/xcssun/users/rms/foo"
     ;; /usr/local/ был отброшен.

Иногда раскрывать имена файлов нежелательно. В таких случаях имя файла можно заключить в кавычки, чтобы подавить раскрытие и обрабатывать имя файла буквально. Экранирование выполняется путём добавления к имени файла префикса ‘/:’.

Макрос: file-name-quote name

Этот макрос добавляет префикс экранирования ‘/:’ к файлу name. Для локального файла name он добавляет к name префикс ‘/:’. Если name — это удалённое имя файла, локальная часть name (см. Превращение некоторых имён файлов в “волшебные”) заключается в кавычки. Если name уже является экранированным именем файла, возвращается name без изменений.

(substitute-in-file-name (file-name-quote "bar/~/foo"))
     ⇒ "/:bar/~/foo"

(substitute-in-file-name (file-name-quote "/ssh:host:bar/~/foo"))
     ⇒ "/ssh:host:/:bar/~/foo"

Макрос не может использоваться для подавления обработчиков имён файлов для волшебных имён файлов (см. Превращение некоторых имён файлов в “волшебные”).

Макрос: file-name-unquote name

Этот макрос удаляет префикс экранирования ‘/:’ из файла name, если он есть. Если name — это удалённое имя файла, локальная часть name раскрывается.

Макрос: file-name-quoted-p name

Этот макрос возвращает не nil, если name экранировано с помощью префикса ‘/:’. Если name — это удалённое имя файла, проверяется локальная часть name.