stfnbms · 2022-02-24 10:02
When trying to open, from dired, a file in a deep subdirectory, I get an error like:
after-find-file: Getting attributes: File name too long, /home/xxxxxx/xxx/emacs-auto-save/#!home!xxxxxx!xxxxxx!xxxxxxxxxxxxx xxxxxxxxxxxxx xxx xxxxxxxx!xxxxxxxx!xxxxxxxxxxxxxxxxxxx xxxx!xx.x.xx xxxxxxxx xxxxxxxxxxxxxxxxxxx_xxxx.xxxx#
How can I fix this? I do like to organize my data in sometimes deeply nested subdirectories.
[deleted] · 2022-02-24 10:54
The issue probably is caused by auto-save transforming an absolute path into a single file name, that results in a file that is too long for either your file system or operating system. You could disable auto-save-mode (not recommended) or store the auto-save files in your current working directory.
Either way, it is worth reporting as a bug.
stfnbms · 2022-02-24 11:08
Thank you. My operating system is Ubuntu GNU/Linux, and the maximum file length there is supposedly 255 bytes. The autosave file name in question is 143 characters long (176 with leading path). All those characters are ASCII, so that should be no more than 176 bytes even in Emacs’s internal UTF-8 character coding. Mmh.
[deleted] · 2022-02-24 11:17
The absolute path length of the auto-save file shouldn't be the issue here. Maybe try evaluating this in the same file system:
(catch 'fail
(with-temp-buffer
(cl-loop for i from 1 do
(let ((buffer-file-name (make-string i ?x)))
(condition-case nil
(write-file buffer-file-name)
(file-error (throw 'fail i)))
(delete-file buffer-file-name)))))
It should fail when you reach the maximum file length has been reached.
hlissner · 2022-02-24 11:24
I've run into this before. I ended up [advising `make-backup-file-name-1` and `make-auto-save-file-name` in Doom Emacs](https://github.com/hlissner/doom-emacs/blob/master/core/core-editor.el#L140-L180) to hash the file name instead (reduces them to a stable 40 characters).
I've converted the Doom advice into vanilla elisp:
```elisp
(defun doom-make-hashed-auto-save-file-name-a (fn)
"Compress the auto-save file name so paths don't get too long."
(let ((buffer-file-name
(if (or (null buffer-file-name)
(find-file-name-handler buffer-file-name 'make-auto-save-file-name))
buffer-file-name
(sha1 buffer-file-name))))
(funcall fn)))
(advice-add #'make-auto-save-file-name :around #'doom-make-hashed-auto-save-file-name-a)
(defun doom-make-hashed-backup-file-name-a (fn file)
"A few places use the backup file name so paths don't get too long."
(let ((alist backup-directory-alist)
backup-directory)
(while alist
(let ((elt (car alist)))
(if (string-match (car elt) file)
(setq backup-directory (cdr elt) alist nil)
(setq alist (cdr alist)))))
(let ((file (funcall fn file)))
(if (or (null backup-directory)
(not (file-name-absolute-p backup-directory)))
file
(expand-file-name (sha1 (file-name-nondirectory file))
(file-name-directory file))))))
(advice-add #'make-backup-file-name-1 :around #'doom-make-hashed-backup-file-name-a)
```
I think this should be done upstream though, so it's worth reporting.
stfnbms · 2022-02-24 11:37
Thank you, that was fun. Apparently, the maximum file length is 142 characters.
stfnbms · 2022-02-24 11:40
Well, what I did now is having Emacs put auto-save files in the same directory as the original file (default behavior, okay since auto-save files do not stay around normally), and disable backup files entirely (I have a daily backup routine for the entire disk, and that Emacs backup folder – now deleted – had added up to 1.7 GB).
nufra · 2022-08-01 13:52
I’d like to propose an improvement: keep the filename if it is < 100 chars to get better performance from lexical ordering in filesystems and make it easier to identify files. If it is longer, keep the first 58 chars and hash the rest. Practically: replace sha1 with this sha1-the-tail:
(defun sha1-the-tail (filename)
"Hash part of the filename but keep initial 58 chars to make it distinguishable."
(let ((shortened (string-limit filename 100)))
(if (equal shortened filename)
filename
(let ((first-58-chars (string-limit shortened 58))
(later-part-to-hash (substring filename 58)))
(concat first-58-chars "-" (sha1 later-part-to-hash))))))
(the idea for this trick is taken from Mercurial)