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)