File 如何使用Elisp删除文件名(路径)中的双点

File 如何使用Elisp删除文件名(路径)中的双点,file,emacs,path,File,Emacs,Path,我正在寻找一种方法来移除。。并得到一条没有。 例如,假设有一条给定的路径 a/b/c/../../1 那么我想从上面得到 a/1 我曾尝试使用文件truename,但它在给定路径的开头预先添加了默认目录 有什么方便的方法吗?请让我知道 PS:如果可能的话,我希望避免使用文件truename。a/b/c/../1不是真正的路径(绝对文件名,用Emacs的说法)。路径以目录开头 最多,该模式是一个相对文件名。相对于什么?在Emacs中,默认情况下,默认目录 也许你真正的意思是/a/b/c/../

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

a/b/c/../../1
那么我想从上面得到

a/1
我曾尝试使用文件truename,但它在给定路径的开头预先添加了默认目录

有什么方便的方法吗?请让我知道


PS:如果可能的话,我希望避免使用文件truename。

a/b/c/../1
不是真正的路径(绝对文件名,用Emacs的说法)。路径以目录开头

最多,该模式是一个相对文件名。相对于什么?在Emacs中,默认情况下,
默认目录

也许你真正的意思是
/a/b/c/../1
,这是一个绝对的文件名(“路径”)?如果您使用它,那么,正如您所说,
filetruename
会提供您想要的。
扩展文件名也是如此

如果您真的想按摩
a/b/c/./../1
来生成
a/1
,那么可以使用
展开文件名
“/”
作为默认目录参数。或者像这样
文件truename

(let ((default-directory  "/"))
  (file-truename "a/b/c/../../1"))
当然,您可以在命名函数中使用它:

(defun foo (relname)
  (let ((default-directory  "/"))
    (file-truename relname)))
当然,这将为您提供
/a/1
,而不是
a/1
。如果确实需要后者,则只需使用
子字符串
删除第一个
/


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

a/b/c/./../1
不是真正的路径(绝对文件名,用Emacs的说法)。路径以目录开头

最多,该模式是一个相对文件名。相对于什么?在Emacs中,默认情况下,
默认目录

也许你真正的意思是
/a/b/c/../1
,这是一个绝对的文件名(“路径”)?如果您使用它,那么,正如您所说,
filetruename
会提供您想要的。
扩展文件名也是如此

如果您真的想按摩
a/b/c/./../1
来生成
a/1
,那么可以使用
展开文件名
“/”
作为默认目录参数。或者像这样
文件truename

(let ((default-directory  "/"))
  (file-truename "a/b/c/../../1"))
当然,您可以在命名函数中使用它:

(defun foo (relname)
  (let ((default-directory  "/"))
    (file-truename relname)))
当然,这将为您提供
/a/1
,而不是
a/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")))

您可以使用普通字符串操作来实现这一点。因此,您不需要使用仅当文件实际存在于文件系统中时才起作用的函数

下面的函数拆分
/
: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")))