在 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.