【问题标题】:Recursively adding .org files in a top-level directory for org-agenda-files takes a long time在 org-agenda-files 的顶级目录中递归添加 .org 文件需要很长时间
【发布时间】:2025-11-02 12:10:01
【问题描述】:

我正在尝试找到一种方法来快速递归搜索 org 文件的每个子目录。我找到了几种解决方案(Elisp Cookbookgithub 上的几个solutions),但它们无法处理我的实际使用情况(数百个目录(和子目录)和数百个组织文件)。它们似乎在我的系统上永远运行(Windows 7,max-lisp-eval-depth = 10000)。我的解决方法是将每个目录手动添加到我的 org-agenda-list 中,但这很烦人,我知道我可能已经忘记了一些。任何建议将不胜感激。

【问题讨论】:

    标签: emacs elisp org-mode


    【解决方案1】:

    没有看到其他人发这个,所以我会做。 您是否尝试过加载“find-list”库并使用它的“find-lisp-find-files”功能? 我在我的组织配置中添加了这些行并且它可以工作,但它可能不符合您的性能要求:

    (load-library "find-lisp") (setq org-agenda-files (find-lisp-find-files "FOLDERNAME" "\.org$"))

    来源:http://emacs-orgmode.gnu.narkive.com/n5bQRs5t/o-multiple-recursive-directories-with-org-agenda-files

    【讨论】:

      【解决方案2】:

      以下代码在 emacs 24.3+ 中运行良好:

      ;; Collect all .org from my Org directory and subdirs
      (setq org-agenda-file-regexp "\\`[^.].*\\.org\\'") ; default value
      (defun load-org-agenda-files-recursively (dir) "Find all directories in DIR."
          (unless (file-directory-p dir) (error "Not a directory `%s'" dir))
          (unless (equal (directory-files dir nil org-agenda-file-regexp t) nil)
            (add-to-list 'org-agenda-files dir)
          )
          (dolist (file (directory-files dir nil nil t))
              (unless (member file '("." ".."))
                  (let ((file (concat dir file "/")))
                      (when (file-directory-p file)
                          (load-org-agenda-files-recursively file)
                      )
                  )
              )
          )
      )
      (load-org-agenda-files-recursively "/path/to/your/org/dir/" ) ; trailing slash required
      

      它不需要创建中间文件,您也可以将它放在快捷方式上。

      为了能够重新归档到找到的任何文件,请添加以下内容:

      (setq org-refile-targets
            '((nil :maxlevel . 3)
              (org-agenda-files :maxlevel . 1)))
      

      【讨论】:

      • 还可以配置 emacs 以获取议程文件列表以进行重新归档。请参阅上面的编辑。
      • 刚刚添加了一个修复程序,仅将目录添加到列表中,这些目录已经包含 .org 文件。
      【解决方案3】:

      当您知道目录结构已更改并且您有时间时,如何将 org-agenda 目录列表存储在您(自动)每隔一段时间更新一次的文件中。

      例如,您可以使用以下内容:

      ;; From http://www.emacswiki.org/emacs/ElispCookbook#toc58
      (defun directory-dirs (dir)
        "Find all directories in DIR."
        (unless (file-directory-p dir)
          (error "Not a directory `%s'" dir))
        (let ((dir (directory-file-name dir))
              (dirs '())
              (files (directory-files dir nil nil t)))
          (dolist (file files)
            (unless (member file '("." ".."))
              (let ((file (concat dir "/" file)))
                (when (file-directory-p file)
                  (setq dirs (append (cons file
                                           (directory-dirs file))
                                     dirs))))))
          dirs))
      
      
      (setq my-org-agenda-root "~/org")
      (setq my-org-agenda-files-list "~/.emacs.d/org-agenda-list.el")
      
      (defun my-update-org-agenda-files ()
        "Create or update the `my-org-agenda-files-list' file.
      
      This file contains elisp code to set `org-agenda-files' to a
      recursive list of all children under `my-org-agenda-root'. "
        (interactive)
        (with-temp-buffer
          (insert
           ";; Warning: this file has been automatically generated\n"
           ";; by `my-update-org-agenda-files'\n")
          (let ((dir-list (directory-dirs my-org-agenda-root))
                (print-level nil)
                (print-length nil))
            (cl-prettyprint `(setq org-agenda-files (quote ,dir-list))))
          (write-file my-org-agenda-files-list)))
      
      (load my-org-agenda-files-list)
      

      每隔一段时间,运行 M-xmy-update-org-agenda-files 来更新列表。

      【讨论】:

        【解决方案4】:

        我还在 Emacs 启动时尝试了“递归目录列表”。这只是一种可以使用的方式。因此,请尽量坚持使用有限数量的“根”目录来放置议程文件。

        更好的是坚持使用“~/org”,可能还有一些子目录,比如“work”和“personal”,仅此而已。您可以将议程文件放在那里,并在其中包含指向您真实项目根目录的链接。

        我知道,这不是最佳选择,但我现在没有更好的选择。

        【讨论】:

          【解决方案5】:

          从 Emacs 25 开始,您可以使用 directory-files-recursively 从根目录返回与正则表达式匹配的所有文件。

          (defun org-get-agenda-files-recursively (dir)
            "Get org agenda files from root DIR."
            (directory-files-recursively dir "\.org$"))
          
          (defun org-set-agenda-files-recursively (dir)
            "Set org-agenda files from root DIR."
            (setq org-agenda-files 
              (org-get-agenda-files-recursively dir)))
          
          (defun org-add-agenda-files-recursively (dir)
            "Add org-agenda files from root DIR."
            (nconc org-agenda-files 
              (org-get-agenda-files-recursively dir)))
          
          (setq org-agenda-files nil) ; zero out for testing
          
          (org-set-agenda-files-recursively "~/Github") ; test set
          
          (org-add-agenda-files-recursively "~/Dropbox") ; test add 
          

          您可以通过输入C-hv org-agenda-files查看org-agenda-files的内容。

          【讨论】:

            最近更新 更多