目录名(directory name)是一个字符串,只要它指向某个文件,就必须指向一个目录。 目录本质上也是一种文件,它拥有一个文件名(称为目录文件名称(directory file name)), 该名称与目录名相关,但通常并不完全相同。 (这与通常的 POSIX 术语略有区别。) 同一实体的这两种名称通过语法转换相互关联。
在 GNU 及类 POSIX 系统上,转换规则很简单: 对一个尚未以 ‘/’ 结尾的目录文件名,在末尾添加 ‘/’ 即可得到目录名。 在 MS-DOS 上,二者关系更为复杂。
目录名与目录文件名称之间的区别细微但至关重要。
当某个 Emacs 变量或函数参数被说明为目录名时,
传入目录文件名称是不被接受的。
file-name-directory 返回的字符串始终是目录名。
下面两个函数用于在目录名与目录文件名称之间转换。 它们不会对环境变量替换(如 ‘$HOME’) 以及 ‘~’、‘.’、‘..’ 等结构做特殊处理。
该函数返回一个字符串, 表示操作系统会将 filename 解析为目录的形式(即目录名)。 在大多数系统上,这意味着在字符串末尾添加斜杠(如果原本没有)。
(file-name-as-directory "~rms/lewis")
⇒ "~rms/lewis/"
若 filename 以目录分隔符结尾,该函数返回非 nil。
在 GNU 及类 POSIX 系统上目录分隔符为正斜杠 ‘/’;
MS-Windows 与 MS-DOS 同时识别正斜杠与反斜杠 ‘\’ 作为目录分隔符。
该函数返回一个字符串, 表示操作系统会将 dirname 解析为普通文件的形式(即目录文件名称)。 在大多数系统上,这意味着移除字符串末尾的目录分隔符, 除非该字符串完全由目录分隔符组成。
(directory-file-name "~lewis/")
⇒ "~lewis"
将 components 拼接至 directory 之后, 若 directory 或前一个组件未以斜杠结尾, 则在组件前自动插入斜杠。
(file-name-concat "/tmp" "foo")
⇒ "/tmp/foo"
值为 nil 或空字符串的 directory 或组件会被忽略——
它们会被优先过滤,且不会对结果产生任何影响。
该函数与直接使用 concat 效果几乎一致,
区别在于 dirname(以及非末尾组件)无论是否以斜杠结尾,
本函数都不会产生重复斜杠。
大多数场景下,使用一次或多次 expand-file-name
(see 文件名展开相关函数)生成带前置目录的文件名,
会比本函数更合适。
仅当 expand-file-name 的某些特殊处理与程序需求冲突时,
才使用本函数。
例如,expand-file-name 对 ~、~user、
nil 的特殊处理,或是对 . 和 .. 的移除,
可能并非你所期望的行为。
如需将目录名转换为缩写形式,可使用以下函数:
该函数返回 filename 的缩写形式。
它会先应用 directory-abbrev-alist 中指定的缩写规则
(see File Aliases in The GNU Emacs Manual),
若参数指向用户主目录或其子目录下的文件,
再用 ‘~’ 替换主目录路径。
若主目录本身为根目录,则不会替换为 ‘~’,
因为在多数系统上这并不会缩短路径。
该函数既可用于目录名,也可用于普通文件名, 因为它能识别名称中任意位置的缩写。
该函数返回 filename 所在父目录的目录名。
若 filename 位于文件系统根目录,则返回 nil。
若 filename 为相对路径,则假定其相对于 default-directory,
此时返回值也为相对路径。
若返回值非 nil,则一定以斜杠结尾。