首先,19.1.1 Namestrings as Filenames 说,namestring(作为路径名的字符串)确实不可移植。
一个符合标准的程序绝不能无条件地使用除逻辑路径名名称字符串之外的文字名称字符串,因为 Common Lisp 没有定义任何名称字符串语法,除了可以保证可移植的逻辑路径名。
另请注意,如果您向用户询问文件名,您可以便携地使用它们:
但是,如果小心,符合标准的程序可以成功地操作包含或引用不可移植名称字符串的用户提供的数据。
您有两个选项,它们并不互斥:使用路径名构造函数,和/或使用逻辑路径名。
路径名构造函数
使用make-pathname、merge-pathnames 构建路径名。路径名是具有不同组件(目录、名称、类型等)的结构,它们可以组合在一起。它们是使用prototypal inheritance 方法构建的,您可以通过复制现有路径名并更改其某些组件来创建新路径名。
make-pathname 就像一个结构构造函数,除了它有一个 :defaults 参数,它提供了一个路径名用作原型。
merge-pathnames 有点不同,因为它也执行语义操作。
例如,如果*default-pathname-defaults*,保存默认路径名的特殊变量,设置如下:
USER> (setf *default-pathname-defaults*
(make-pathname :directory '(:relative "crossover-operator")))
#P"crossover-operator/"
那么你有两种不同的行为。
USER> (make-pathname :directory '(:relative "tmp")
:defaults *default-pathname-defaults*)
#P"tmp/"
make-pathname 替换原路径名的目录部分。
USER> (merge-pathnames *)
#P"crossover-operator/tmp/"
merge-pathnames 采用路径名(这里是我们刚刚构建的路径名,用* 表示),并将相对于*default-pathname-defaults* 中的目录合并。
逻辑路径名
逻辑路径名有点像 URL(统一资源定位器),只是间接表示文件。程序员必须根据地址的HOST 部分定义从逻辑路径名到实际物理路径名的翻译函数。
路径名(名称字符串)的打印表示是不可移植的,除了逻辑路径名。见19.3.1 Syntax of Logical Pathname Namestrings。
除了具有定义的语法和翻译功能(从逻辑路径名到物理路径名)外,它们的行为与其他路径名一样,因此您可以调用merge-pathnames,如上所示。
路径名翻译可以映射到不可移植的名称字符串(但您可以在不同的主机上设置不同的翻译),也可以映射到逻辑或物理路径名。 LOGICAL-PATHNAME-TRANSLATIONS 的超规范有一些关于如何使用逻辑路径名的示例,如下所示:
;;;A more complex example, dividing the files among two file servers
;;;and several different directories. This Unix doesn't support
;;;:WILD-INFERIORS in the directory, so each directory level must
;;;be translated individually. No file name or type translations
;;;are required except for .MAIL to .MBX.
;;;The namestring syntax on the right-hand side is implementation-dependent.
(setf (logical-pathname-translations "prog")
'(("RELEASED;*.*.*" "MY-UNIX:/sys/bin/my-prog/")
("RELEASED;*;*.*.*" "MY-UNIX:/sys/bin/my-prog/*/")
("EXPERIMENTAL;*.*.*" "MY-UNIX:/usr/Joe/development/prog/")
("EXPERIMENTAL;DOCUMENTATION;*.*.*"
"MY-VAX:SYS$DISK:[JOE.DOC]")
("EXPERIMENTAL;*;*.*.*" "MY-UNIX:/usr/Joe/development/prog/*/")
("MAIL;**;*.MAIL" "MY-VAX:SYS$DISK:[JOE.MAIL.PROG...]*.MBX")))
;;;Sample use of that logical pathname. The return value
;;;is implementation-dependent.
(translate-logical-pathname "prog:mail;save;ideas.mail.3")
=> #P"MY-VAX:SYS$DISK:[JOE.MAIL.PROG.SAVE]IDEAS.MBX.3"