在 Common Lisp 中获取相对路径
Get relative path in Common Lisp
给定一个目录的任意路径 path
和一些其他路径 base
,我怎样才能获得从 base
到文件系统中与 path
?
比如(relpath #p"~/foo" #p"~/bar/")
必须给我#p"../foo"
。比如Julia里面就有这样一个函数,也叫relpath
。 Common Lisp 中是否有类似的东西(标准库或第三方库)?
最接近您要查找的内容称为 enough-namestring
:
(enough-namestring "~/foo/bar/baz" "~/foo/")
==> "bar/baz"
如果两个路径都存在,您可以通过调用 truename
将它们规范化为绝对路径名;然后,由于路径名目录是列表,您可以轻松找到最长的公共路径,并根据需要构建具有尽可能多的 :up
元素的相对路径名,从第二个路径名到第一个:
(defun rp (p1 p2)
(loop
for d1 on (pathname-directory (truename p1))
for d2 on (pathname-directory (truename p2))
while (string= (first d1) (first d2))
finally
(return
(make-pathname
:directory (append (list :relative)
(substitute :up t d2 :test (constantly t))
d1)
:defaults p1))))
例如,假设“/tmp/foo”存在且“~”为“/home/user/”:
> (rp "/tmp/foo" "~/")
#P"../../tmp/foo"
这应该涵盖了很多常见的用例,但这有其局限性(没有通配符名称,文件必须存在,可能还有其他极端情况)
我知道这个问题与常见的 lisp 有关,但作为提示,emacs lisp 中有一个解决方案。 emacs lisp函数return的相对路径是file-relative-name.
给定一个目录的任意路径 path
和一些其他路径 base
,我怎样才能获得从 base
到文件系统中与 path
?
比如(relpath #p"~/foo" #p"~/bar/")
必须给我#p"../foo"
。比如Julia里面就有这样一个函数,也叫relpath
。 Common Lisp 中是否有类似的东西(标准库或第三方库)?
最接近您要查找的内容称为 enough-namestring
:
(enough-namestring "~/foo/bar/baz" "~/foo/")
==> "bar/baz"
如果两个路径都存在,您可以通过调用 truename
将它们规范化为绝对路径名;然后,由于路径名目录是列表,您可以轻松找到最长的公共路径,并根据需要构建具有尽可能多的 :up
元素的相对路径名,从第二个路径名到第一个:
(defun rp (p1 p2)
(loop
for d1 on (pathname-directory (truename p1))
for d2 on (pathname-directory (truename p2))
while (string= (first d1) (first d2))
finally
(return
(make-pathname
:directory (append (list :relative)
(substitute :up t d2 :test (constantly t))
d1)
:defaults p1))))
例如,假设“/tmp/foo”存在且“~”为“/home/user/”:
> (rp "/tmp/foo" "~/")
#P"../../tmp/foo"
这应该涵盖了很多常见的用例,但这有其局限性(没有通配符名称,文件必须存在,可能还有其他极端情况)
我知道这个问题与常见的 lisp 有关,但作为提示,emacs lisp 中有一个解决方案。 emacs lisp函数return的相对路径是file-relative-name.