Backup 如何控制Emacs动态备份文件的目录?

Backup 如何控制Emacs动态备份文件的目录?,backup,Backup,我看过这篇文章和一些类似的文章,它们展示了非常相似的解决方案。我很清楚这种方法。但它并没有达到我想要的效果。我希望我要备份的每个文件都有自己的个性化备份目录 例如,假设我在当前目录中有以下文件,/Users/me/project\u a/ apple.txt banana.txt coconut.txt 编辑这些文件时,我希望它们的备份存储在以下目录中: /Users/me/project_a/.backups/apple.txt/ /Users/me/project_a/.backups/b

我看过这篇文章和一些类似的文章,它们展示了非常相似的解决方案。我很清楚这种方法。但它并没有达到我想要的效果。我希望我要备份的每个文件都有自己的个性化备份目录

例如,假设我在当前目录中有以下文件,
/Users/me/project\u a/

apple.txt
banana.txt
coconut.txt
编辑这些文件时,我希望它们的备份存储在以下目录中:

/Users/me/project_a/.backups/apple.txt/
/Users/me/project_a/.backups/banana.txt/
/Users/me/project_a/.backups/coconut.txt/
如果我需要另一个项目目录,比如
/Users/me/project\u b/
,以及文件

needle.doc
thread.doc
thimble.doc
然后,它们各自的备份应位于

/Users/me/project_b/.backups/needle.doc/
/Users/me/project_b/.backups/thread.doc/
/Users/me/project_b/.backups/thimble.doc/
是的,我正在使用要备份的文件的名称作为保存该文件的目录的路径名的一部分。因此,如果我有三个以前版本的
thimble.doc
,那么备份的完整路径名将是:

/Users/me/project_b/.backups/thimble.doc/thimble.doc.~1~
/Users/me/project_b/.backups/thimble.doc/thimble.doc.~2~
/Users/me/project_b/.backups/thimble.doc/thimble.doc.~3~
我有一个解决办法来实现这一点(见下文)。理想情况下,我会将备份命名为:

/Users/me/project_b/.backups/thimble.doc/bak.~1~
/Users/me/project_b/.backups/thimble.doc/bak.~2~
/Users/me/project_b/.backups/thimble.doc/bak.~3~
我还不知道怎么去那里。(有什么建议吗?)

下面是我如何使用
.dir locals.el
文件和以下用于保存
.txt
.tex
文件的代码来实现这个不太理想的版本

  (let (a b)
    (dolist (ae-fh (directory-files-recursively "." "\\.\\(txt\\|tex\\)$"))
      (setq a (file-name-nondirectory ae-fh))
      (setq a (replace-regexp-in-string "\\." "\\\\." a))
      (setq b (concat "./.backups/" (file-name-nondirectory ae-fh)))
      (add-to-list 'backup-directory-alist (cons a b))             
      ))
我已经将
备份目录列表
设置为缓冲区本地变量

这实现了我想要的,但我不太喜欢这种方法。我希望完全避免使用
.dir locals.el
作为此问题的解决方案。但同时,我希望避免将
备份目录
废弃。如果有一个钩子可以应用于备份过程,它可以动态地通知emacs应该如何命名备份文件,那就太好了

有人知道怎么做吗,或者知道我该去哪里吗?我曾考虑过尝试重新定义
使备份文件名功能
,但我不完全理解我在用elisp做什么,现在我有一些项目需要处理


人们能告诉我什么?

我有一个部分解决方案

  • 它避免了使用我想要的
    .dir locals.el
  • 它在某种程度上创建了我想要的动态路径
  • 它仍然使用备份目录列表
我将以下内容添加到我的emacs init文件中:

 (add-hook 'after-change-major-mode-hook 
           '(lambda ()
              (let (a b)
                (if (stringp (buffer-file-name))
                (progn
                  (setq a (file-name-nondirectory (buffer-file-name)))
                  (setq a (replace-regexp-in-string "\\." "\\\\." a))
                  (setq b (concat "./.backups/" (file-name-nondirectory (buffer-file-name))))
                  (add-to-list 'backup-directory-alist (cons a b))             
                      )
                  )
                )))
我对这个钩子的了解还不够。所以,我不确定这是否会一直有效。而且,我可能会考虑是否有文件,这个公约真的是不受欢迎的。
(stringp(缓冲区文件名))
对于没有底层文件的缓冲区来说是最基本的必要条件:例如
*scratch*
甚至是迷你缓冲区

我仍然对其他人可能提出的解决方案感兴趣。理想情况下,解决方案更像

/Users/me/project_b/.backups/thimble.doc/bak.~1~
/Users/me/project_b/.backups/thimble.doc/bak.~2~
/Users/me/project_b/.backups/thimble.doc/bak.~3~

更新:坚持会让你成功

我最后在谷歌上搜索了一下:“emacs我如何重新定义
生成备份文件名
”。我找到了适合自己情况的方法。也就是说,我做了以下工作:

(defun z:backup:truncate.backup.name (file)
  (concat (file-name-directory file) "bak"))
(advice-add 'make-backup-file-name-1 :filter-return #'z:backup:truncate.backup.name)
我不完全确定一切都是关于什么的

  • 我不知道
    #
    语法的作用
  • 我不确定<代码>:过滤器返回的作用,尽管我可以猜测
我应该指出,对于
'after-change-major-mode-hook
,我仍然需要mae
添加hook
。没有它,我会出错。显然,我就是不能把建议函数写成

(defun z:backup:truncate.backup.name (file)
  (concat (file-name-directory file) (file-name-nondirectory) "/bak"))
我试过了,但出现了一个错误,就是无法备份。我认为这是因为
备份目录列表
用于确定目录路径。我对这里的一些调整有一些想法。但这就是目前的情况

更新:更改主模式挂钩后,不再需要我的
将挂钩添加到

我已经解决了备份目录列表不一定设置为正确目录的问题。这是我对
z:backup:truncate.backup.name的最终形式

(defun z:backup:truncate.backup.name ()
  (let* (
         (dir  (file-name-directory (buffer-file-name)))
         (fh   (file-name-nondirectory (buffer-file-name)))
         (qdir (concat dir ".backups/" fh))
          )
    (if (not (file-directory-p qdir))
        (progn
          (if (file-directory-p dir)
              (progn
                (make-directory qdir)
                ))))
  (concat qdir "/bak")))
因此,现在更需要调整备份目录列表。我已经完成了我想要的一切。嗯

(defun z:backup:truncate.backup.name ()
  (let* (
         (dir  (file-name-directory (buffer-file-name)))
         (fh   (file-name-nondirectory (buffer-file-name)))
         (qdir (concat dir ".backups/" fh))
          )
    (if (not (file-directory-p qdir))
        (progn
          (if (file-directory-p dir)
              (progn
                (make-directory qdir)
                ))))
  (concat qdir "/bak")))