【问题标题】:Faster Emacs directory walker更快的 Emacs 目录遍历器
【发布时间】:2014-09-13 21:39:23
【问题描述】:

使用说明书 (http://www.emacswiki.org/emacs/ElispCookbook#toc59) 在 Emacs 中遍历目录树,或者 Walk up the directory tree 的解决方案非常慢。

是否可以通过shell-commandcall-process 改用Unix 的find,并在返回的列表上执行funcall

这个想法有什么缺点(也许大树的内存消耗太多?),在 elisp 中这样做的惯用方法是什么,即使用一些给定的参数调用 find 并在返回值?

我可以看到的一个可能的好处是,shell 进程可以异步启动,而 Emacs 在进程启动时根本不会停止。

【问题讨论】:

    标签: emacs elisp


    【解决方案1】:

    是的,当然您可以通过call-process 调用find,然后逐行拆分结果。请注意,使用file-name-all-completions 代替directory-filesfile-directory-p 可以显着提高walk-path 的效率:

    (defun my-walk-directory (dir action)
      "walk DIR executing ACTION with (dir file).
    DIR needs to end with /."
      (dolist (file (let ((completion-ignored-extensions nil)
                          (completion-regexp-list nil))
                      (file-name-all-completions "" dir)))
        (cond
         ((member file '("./" "../")) nil)
         ((eq ?/ (aref file (1- (length file)))) (my-walk-directory (concat dir file) action))
         (t (funcall action dir file)))))
    

    当然,它仍然不会像find 那样快,但根据我的经验,这比使用目录文件加上文件目录-p 快大约 10 倍。

    【讨论】:

    • 使用显式目录堆栈展开递归不会使函数更高效吗?我虽然在 Emacs Lisp 中函数调用相当慢。
    • 我认为差异是无法衡量的。当然,请随意尝试。
    • @Stefan, @lunaryorn 谢谢你的回答和额外的信息。我也想尝试使用 Unix 选项,并比较速度。你能给我一个指针,告诉我如何将call-process 返回的值转换为列表,或者如你所说的如何逐行拆分结果?
    • call-process 可以将结果放入当前缓冲区,因此您可以使用search-forward 查找下一个\n,然后使用buffer-substring 提取您刚刚找到的行。
    • @Stefan,非常感谢。作为参考,我最近发现了一篇关于加速文件查找的文章。 unixlore.net/articles/speeding-up-bulk-file-operations.html 有趣的是,最后一个 Perl 解决方案比连续运行两个 xargs 命令要快。当然,使用新数据库的 gnu locate 应该是迄今为止最快的。
    猜你喜欢
    • 2011-03-10
    • 2016-07-24
    • 2016-01-22
    • 2018-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多