如何使用Elisp

时间:2016-12-15 14:01:06

标签: file emacs path

我正在寻找一种方法来移除..并获得一条没有...的路径。 例如,假设存在给定路径

a/b/c/../../1

然后我想从上面得到

a/1

我尝试使用file-truename,但它在给定路径的开头添加了default-directory。

有没有方便的方法?请告诉我。

PS:如果可能,我想避免使用file-truename。

2 个答案:

答案 0 :(得分:3)

a/b/c/../../1实际上并不是一个路径(绝对文件名,在Emacs的说法中)。路径以目录开头。

最多,该模式是相对文件名。相对于什么?在Emacs中,默认为default-directory

也许你真正的意思是/a/b/c/../../1,这是一个绝对的文件名("路径")?如果您使用它,正如您所说,file-truename可以为您提供所需内容。 expand-file-name也是如此。

如果您真的想要按a/b/c/../../1来生成a/1,那么您可以使用expand-file-name "/"作为默认目录参数来执行此操作。或file-truename喜欢这样:

(let ((default-directory  "/"))
  (file-truename "a/b/c/../../1"))

您当然可以在命名函数中使用它:

(defun foo (relname)
  (let ((default-directory  "/"))
    (file-truename relname)))

当然,这会为您提供/a/1,而不是a/1。如果你真的想要后者,那么只需使用substring删除第一个/

(也许你可以告诉我们你需要的用例。它可能会改变你得到的建议,从而更有帮助。)

答案 1 :(得分:1)

您可以使用纯字符串操作来执行此操作。因此,您不需要使用仅在文件实际存在于文件系统中时才起作用的函数。

下面的函数将字符串拆分为/:s并遍历结果列表。它会忽略任何.,只要它看到..它就会看到已经看到的路径组件。

例如:

(defun my-simplify-path (path)
  "Simplify PATH by removing redundant parts.

The operation is only performed using string operations, so PATH
does not have to exist in the file system."
  (let ((old-list (split-string path "/"))
        (new-list-reversed '()))
    (dolist (element old-list)
      (cond ((equal element "."))
            ((and (equal element "..")
                  (not (null new-list-reversed)))
             (pop new-list-reversed))
            (t
             (push element new-list-reversed))))
    (if (null new-list-reversed)
        "."
      (string-join (nreverse new-list-reversed) "/"))))

以下ERT测试用例演示了此功能的工作原理:

(ert-deftest my-simplify-path-test ()
  (should (equal (my-simplify-path "alpha") "alpha"))
  (should (equal (my-simplify-path "./alpha") "alpha"))
  (should (equal (my-simplify-path "alpha/./beta") "alpha/beta"))
  (should (equal (my-simplify-path "alpha/beta") "alpha/beta"))
  (should (equal (my-simplify-path "alpha/../beta") "beta"))
  (should (equal (my-simplify-path "alpha/beta/gamma/delta/../../..") "alpha"))
  (should (equal (my-simplify-path "../alpha") "../alpha"))
  (should (equal (my-simplify-path "alpha/../..") ".."))

  (should (equal (my-simplify-path "a/b/c/../../1") "a/1")))