Common lisp 将带有平铺的文件名扩展到其完整路径(Common Lisp)
我有一个带波浪号的目录名(字符串):Common lisp 将带有平铺的文件名扩展到其完整路径(Common Lisp),common-lisp,home-directory,pathname,Common Lisp,Home Directory,Pathname,我有一个带波浪号的目录名(字符串):~/projects 我想获得它的完整路径:/home/user/projects。我该怎么做 目标是将其传递给uiop:runprogram,这样做似乎不对 回答如下: =>错了 多谢各位 编辑我将分享更多内容 我想通过uiop:launch-program运行一个程序。我有一个用户定义的目录列表,比如~/projects。使用它创建/~/projects目录,而不是/home/user/projects 如果目录不存在,truename将不起作用 在S
~/projects
我想获得它的完整路径:/home/user/projects
。我该怎么做
目标是将其传递给uiop:runprogram
,这样做似乎不对
回答如下: =>错了 多谢各位
编辑我将分享更多内容 我想通过
uiop:launch-program
运行一个程序。我有一个用户定义的目录列表,比如~/projects
。使用它创建/~/projects
目录,而不是/home/user/projects
如果目录不存在,truename
将不起作用
在SBCL上,(名称字符串“~/doesntexist”)
也返回其波浪号
合并路径名
不起作用,仍然是波浪线问题
输入确保目录存在
,并使用此结果创建名为~
的目录
给出答案后,我别无选择,只能调整逻辑以扩展我们实际想要存在的目录的目录名
;; Create a directory
;; Ensure its name (string) ends with a slash.
(setf mydir
(str:concat (string-right-trim (list #\/) mydir)
"/"))
(ensure-directories-exist base)
然后我可以用它的truename
对~
您的Lisp实现可能支持也可能不支持tilde语法
如果是(例如CCL、ABCL、CLISP、ECL、LispWorks),则truename
将始终扩展为文件名:
(truename "~/projects")
=> /home/user/projects
如果您的实现没有,或者如果您希望代码可移植,则必须相对于(用户homedir路径名)
:
注意,如果支持tilde,那么它似乎只支持用作路径名的字符串,而不支持在目录组件中使用<代码>(:relative“~”的工作方式与预期不同,它引用了一个名为“~”的目录
相反,至少对于SBCL,适当的目录是(:absolute:home)
,或者,如果您想引用其他用户,您可以将组件包装在列表中:
(make-pathname :directory '(:absolute (:home "root")))
=> #P"~root/"
扩展到不存在的路径名
truename
是否要求该对象存在
是的,如果您想要构建一个不存在的文件的绝对路径,那么您需要对存在的部分调用truename
,并与之合并。
在您的情况下,这将是(truename“~/”
,它与(user homedir pathname)
相同
正如Rainer Joswig所指出的,在SBCL以外的实现上调用namestring
会返回一个扩展的路径名,将~
转换为/home/user
。在SBCL中,必须调用sbext:native namestring
才能获得相同的效果
换句话说,为了扩展到不一定存在的文件名,您可以编写以下可移植层:
(defun expand-file-name (pathname)
(check-type pathname pathname)
(block nil
#+(or lispworks clozure cmu clisp ccl armedbear ecl)
(return (namestring pathname))
#+sbcl
(return (native-namestring pathname))
#+(not (or sbcl lispworks clozure cmu clisp ccl armedbear ecl))
(let ((expanded (namestring pathname)))
(prog1 expanded
(assert (not find #\~ expanded) ()
"Tilde not supported")))))
如果您的Lisp不支持语法,请参阅以获取灵感。uiop中有一个本机名称字符串函数,该函数应在所有实现中都可用:
(uiop:native-namestring "~/projects")
=> /home/user/projects
truename
会要求该对象存在吗?是的,如果目录不存在,truename
会失败。我喜欢一个支持这个的解决方案。@RainerJoswig是的,如果路径名不存在,似乎没有可移植的方法来解析它,但是truename
仍然可以在预期存在的部分上调用。namestring
可以在许多理解
的实现中工作:CCL、ABCL、CLISP、ECL、LispWorks。SBCL返回tilde名称…在SBCL中打开的问题:请注意,这根本不是特定于CL的问题;通常,在路径离开用户的交互式、兼容POSIX的shell并由应用程序处理之前,tilde会被扩展。没有一个标准的UNIX工具可以进行平铺扩展——如果您运行rm'~/foo.txt'
,它将在名为~
的目录中查找文件——因此一般认为应用程序不会尝试将其放入范围。这是一个很好的提醒!太好了,谢谢!它还适用于不存在的目录名。
(defun expand-file-name (pathname)
(check-type pathname pathname)
(block nil
#+(or lispworks clozure cmu clisp ccl armedbear ecl)
(return (namestring pathname))
#+sbcl
(return (native-namestring pathname))
#+(not (or sbcl lispworks clozure cmu clisp ccl armedbear ecl))
(let ((expanded (namestring pathname)))
(prog1 expanded
(assert (not find #\~ expanded) ()
"Tilde not supported")))))
(uiop:native-namestring "~/projects")
=> /home/user/projects