7

I found different solutions for keeping auto-save files out of the directory where the original file is located on the internet, including

(defconst emacs-tmp-dir (format "%s/%s%s/" "/t" "emacs" (user-uid)))
(setq backup-directory-alist
      `((".*" . ,emacs-tmp-dir)))
(setq auto-save-file-name-transforms
      `((".*" ,emacs-tmp-dir t)))
(setq auto-save-list-file-prefix
      emacs-tmp-dir)

which I currently use.

It works, but only for files on "shallow" levels of my deep directory tree. When editing files many directories down, I get an error message like this (which I partly censored because it got someone else's name in it):

Question

How do I get auto-save to work for these files?

Additional info

This page helped me solve the same problem for backup files ("How to set emacs so backups in one place with tree structure?") but I can't seem to figure out how to solve it for auto-save files. (Just leaving the link here in case the code has only be adapted slightly or someone who has the backup file problem stumbles across this question.)

2
  • 1
    This looks promising. I am trying it now.
    – dmvianna
    Jan 11, 2018 at 5:21
  • @dmvianna Why does the configuration (setq auto-save-file-name-transforms `((".*" ,emacs-tmp-dir t))) look promising? The UNIQUIFY flag is set to t and therefore path is transformed into a long file name. That is exactly what you try to avoid. Isn't it?
    – Tobias
    Jan 12, 2018 at 14:33

1 Answer 1

3
+50

You can avoid the removal of the directory component of auto-save files by setting the UNIQUIFY component in the entries of the variable auto-save-file-name-transforms to nil.

From the doc of auto-save-file-name-transforms:

Transforms to apply to buffer file name before making auto-save file name. Each transform is a list (REGEXP REPLACEMENT UNIQUIFY):

...

If the optional element UNIQUIFY is non-nil, the auto-save file name is constructed by taking the directory part of the replaced file-name, concatenated with the buffer file name with all directory separators changed to ‘!’ to prevent clashes.

In that case you have to make sure that the directory component of the buffer-auto-save-file-name refers to an existing directory. That is possible in auto-save-hook which is run just before saving the auto-save file.

If you want to try this strategy put the following stuff into your init file. But, make sure that there is no other part of your initialization fiddling with auto-save-file-name-transforms! Maybe the only entry in auto-save-file-name-transforms which you can keep is the one for tramp. That entry has a colon in its REGEXP.

Note that you should adapt the value of the option auto-save-dir-base to the needs of your operating system.

(defcustom auto-save-dir-base "/var/tmp/emacs-auto-save"
  "File name base for auto-save-dir.
The real auto save directory name is created by appending the UID of the user.
Restart of emacs required after changes."
  :group 'files
  :type 'directory)

(defun auto-save-ensure-dir ()
  "Ensure that the directory of `buffer-auto-save-file-name' exists.
Can be used in `auto-save-hook'."
  (cl-loop for buf in (buffer-list) do
       (with-current-buffer buf
         (when (and (buffer-file-name) ;; Is this buffer associated with a file?
            (stringp buffer-auto-save-file-name)) ;; Does it have an auto-save-file?
           (let ((dir (file-name-directory buffer-auto-save-file-name)))
         (unless (file-directory-p dir)
           (make-directory dir t)
           ))))))

(add-hook 'auto-save-hook #'auto-save-ensure-dir)

(defun auto-save-dir ()
  "Return the users auto save directory."
  (concat auto-save-dir-base (number-to-string (user-uid))))

(unless (file-directory-p (auto-save-dir))
  (make-directory (auto-save-dir)))

(add-to-list 'auto-save-file-name-transforms (list "\\`.*\\'" (concat (auto-save-dir) "\\&") nil) t)
4
  • I need a solution that will work across operating systems. My difficulty might be different from the original poster. I either seem to get droppings within my projects or I get an error where the /tmp/emacs is set to a name that doesn’t exist.
    – dmvianna
    Jan 13, 2018 at 0:54
  • @dmvianna You can set auto-save-dir-base depending on system-type. That should avoid the problem with the non-existent directory.
    – Tobias
    Jan 13, 2018 at 0:57
  • How about (defcustom auto-save-dir-base (format "%s/%s" temporary-file-directory "emacs-"))?
    – dmvianna
    Jan 13, 2018 at 9:38
  • Thanks, I was able to adapt your solution to my needs (different from the OP, as my problem was not having the emacs-$UID directory).
    – dmvianna
    Jan 13, 2018 at 10:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.