backup - 如何控制 Emacs 将备份文件动态生成到哪个目录?
问题描述
我看过这篇文章如何控制 Emacs 如何制作备份文件? 还有一些类似的帖子显示了非常相似的解决方案。我很清楚这种方法。但它并没有完全按照我的意愿去做。我希望我要备份的每个文件都有自己的个性化备份目录。
例如,假设我在当前目录中有以下文件,/Users/me/project_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_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))
))
我已经创建了backup-directory-alist
一个缓冲区局部变量。
这完成了我想要的,但我不太喜欢这种方法。我想完全避免使用.dir-locals.el
它来解决这个问题。而且,我想避免将backup-directory-alist
. 如果有一个钩子我可以应用到备份过程中会很好地通知 emacs 它应该如何命名备份文件。
有谁知道如何做到这一点或知道在哪里指向我?我考虑过尝试重新定义make-backup-file-name-function
,但我并不完全理解我在用 elisp 做什么,现在我有需要处理的项目。
人家能告诉我什么?
解决方案
我有一个部分解决方案。
- 它避免了
.dir-locals.el
我想要的使用。 - 它在某种程度上也像我想要的那样动态地创建了路径。
- 它仍然使用
backup-directory-alist
我将以下内容添加到我的 emacs 初始化文件中:
(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 (buffer-file-name))
是最低限度的必要条件:例如*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~
比
/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~
更新:坚持会让你有地方!!!!
我终于在谷歌上搜索了:“emacs我如何重新定义make-backup-file-name
”。我发现了这种方法的描述,我适应了我的情况。也就是说,我做了以下事情:
(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)
我不完全确定一切是关于什么的。
- 我不知道
#'
语法是做什么的。 - 我不确定是什么
:filter-return
,虽然我可以猜到。
我应该指出,我仍然需要 mae add-hook
for 'after-change-major-mode-hook
。没有它,我会得到错误。显然,我只是不能将建议功能写为
(defun z:backup:truncate.backup.name (file)
(concat (file-name-directory file) (file-name-nondirectory) "/bak"))
我试了一下,得到一个关于无法备份的错误。而且我认为这样做的原因backup-directory-alist
是用于确定目录路径。我对这里的一些调整有一些想法。但这就是目前的情况。
更新:不再需要我
add-hook
的after-change-major-mode-hook
我已经解决了备份目录 alist 不一定设置为正确目录的问题。这是我的最终形式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")))
所以现在更多的不得不调整backup-directory-alist
。我已经完成了我想要的一切。是的。
推荐阅读
- android - SearchView 小部件文本未与工具栏的左侧/开始对齐
- automation - 无法单击删除按钮,多视图
- c - 返回枚举的名称而不是它的值
- xslt - 从 XSLT 调用 XQuery,在 XQuery 中动态构建 XSLT?
- excel - 如何检查单元格是否存在于不同工作表的范围内,然后引用它
- python - 我在循环中调用一个函数并将结果存储在一个矩阵中,我该如何并行化它?
- python - scipy中的Sobel过滤器实现
- ipython - 蟒蛇。如何在下一行继续代码?
- c# - 如何获得“jan-2018, Feb-2018, Mar-2018”作为下拉列表
- php - 连接失败。错误 #2:stream_socket_client():无法连接到 ssl://smtp.gmail.com:465(连接被拒绝)