gnu emacs backup files

I use GNU Emacs, and I love it. However, one annoyance is that it scatters autosave files (#foo#) and backup files (foo~) all over the filesystem.

So, I finally got fed up with this, and figured out how to keep them all in one place. Here’s the elisp (GNU Emacs only) that I put in my .emacs:

;; Put autosave files (ie #foo#) and backup files (ie foo~) in ~/.emacs.d/.
(custom-set-variables
  '(auto-save-file-name-transforms '((".*" "~/.emacs.d/autosaves/\\1" t)))
  '(backup-directory-alist '((".*" . "~/.emacs.d/backups/"))))

;; create the autosave dir if necessary, since emacs won't.
(make-directory "~/.emacs.d/autosaves/" t)

…and, courtesy of Amit Patel, here’s the elisp for XEmacs.

;;; Auto-save
;;; Load the auto-save.el package, which lets you put all of your autosave
;;; files in one place, instead of scattering them around the file system.
;;; M-x recover-all-files or M-x recover-file to get them back
(defvar temp-directory (concat "/tmp/" (user-login-name)))
(make-directory temp-directory t)

; One of the main issues for me is that my home directory is
; NFS mounted.  By setting all the autosave directories in /tmp,
; things run much quicker
(setq auto-save-directory (concat temp-directory "/autosave")
      auto-save-hash-directory (concat temp-directory "/autosave-hash")
      auto-save-directory-fallback "/tmp/"
      auto-save-list-file-prefix (concat temp-directory "/autosave-")
      auto-save-hash-p nil
      auto-save-timeout 100
      auto-save-interval 300)
(make-directory auto-save-directory t)
(require 'auto-save)

;;; Put backups in another directory.  With the directory-info
;;; variable, you can control which files get backed up where.
(require 'backup-dir)
(setq bkup-backup-directory-info
      \`(
        (t ,(concat temp-directory "/backups") ok-create full-path)
        ))
(setq make-backup-files t)
(setq backup-by-copying t)
(setq backup-by-copying-when-mismatch t)
(setq backup-by-copying-when-linked t)
(setq version-control t)
(setq-default delete-old-versions t)

34 thoughts on “gnu emacs backup files

  1. Thanks a ton!
    Nuisance gone.

    What’s the reason behind different scripts for XEmacs and GNU Emacs?  I knew that the two don’t play nice, but I’m surprised that the .el files are tailored for one or the other.

    Can’t wait to see how they work on EmacsW32!

  2. good point! they’re different because i only wrote the gnu emacs elisp. i provided amit’s xemacs elisp for completeness and convenience only.

    having said that, the gnu emacs code evaluates happily in xemacs, so it just might work. amit’s code, on the other hand, uses auto-save.el, which comes with xemacs but not gnu emacs. it might be a better solution, but it’s xemacs-specific.

  3. It’s amazing how such a simple piece of code eliminates such a pain in the butt problem.  Thanks again.

    I have been thinking though.  (No good deed and what not…)

    I use individual .emacs files per user.  Each user adds your snippet.  Therefore, without any alterations, each user gets a (user-login-name) added to both the /tmp/emacs_backups and /tmp/emacs_autosaves.

    For me, these files are made with the default mask in bash, I guess.  So they get permissions of 755.  No matter what the original file was.  Since /tmp is a public directory, now anyone can read the backups.
    This might be a security risk.

    I’m no bash expert.  So I’m no help.  Sorry.

    Thanks again.

  4. I had a problem where emacs would try and auto-save files to /tmp/emacs_autosaves/arthur//home/arthur/scratch or similar directories. Emacs could not open the file because the directories did not exist. I fixed it by changing make-auto-save-file-name to not add paths to non-file buffers. I’m not where why that was there in the first place.

    (defun make-auto-save-file-name ()
      (concat autosave-dir
      (if buffer-file-name
      (concat “#” (file-name-nondirectory buffer-file-name) “#”)
      (concat “#%” (buffer-name) “#”))))

    Thanks for the script.

  5. It seems that putting them in a central directory puts bangs (!)’s in the file name.  How can you restore a backup in this case, given that ! is a control character in *nix?

  6. hmm, i don’t understand what you mean by “control character in *nix.” do you mean it’s a control character in your shell? just quote the filename – cat "/tmp/bang!file" – or escape the ! – cat /tmp/bang\!file.

  7. I used this code for a while, it works but causes error message in mail buffers. After some investigation I think that this code does the Wrong Thing. The default implementation of make-auto-save-file-name is much more sophisticated, and it uses the variable auto-save-file-name-transforms which allows the user to change the outcome without redefining functions.

    (setq auto-save-file-name-transforms `(("\(?:[^/]/\)\(.*\)" ,(concat autosave-dir "\1") t)))

    Acheives the same goal as the defuns, without breaking autosaves for gnus or tramp.

  8. Thanks for this little tool.

    It helped me at work where non emacs users colleagues complains about all these little files…

  9. Thanks dude ! This is really helpful ! All those crap files are gone ! :-)

  10. Thank you!
    This has been haunting me for years. If one wants to save other users on the system from this plague, you can copy the above code to /etc/emacs/site-start.el instead of into to ~/.emacs file.

  11. Thanks!
    For years I did just live with that nuisance – in reality small one considering all the functionality that Emacs offers! – but it is better now. – George.

  12. setq auto-save-file-name-transforms only works for the auto-save (#) files. The default make-backup-file-name function, defined in files.el, invokes make-backup-file-name-1, which embeds the !path! file name synthesis so there is no way to change these long names for backup (~) files without completely replacing make-backup-file-name function. To shrink auto-save names, the last element of auto-save-file-name-transforms should be nil instead of t. Also, note that the RE is for DOS. For LINUX I use:
    (setq auto-save-file-name-transforms `((“\([^/]/\)\(.*\)”, “~/bak/\2” nil))) making auto-saves userhome\bak\#filename#.

  13. I don’t get it.
    So many people seem to have ‘just lived’ with it.
    Everyone: The /info/ is right there, it is even
    in the FAQ. ‘C-h i’ at your service:
    ,—-[ (info “(efaq)Disabling backups”) ]
    |  Beginning with Emacs 21.1, you can control where Emacs puts backup
    | files by customizing the variable backup-directory-alist'.&nbsp; This<br />
    | variable's value specifies that files whose names match specific patters<br />
    | should have their backups put in certain directories.&nbsp; A typical use is<br />
    | to add the element
    (“.” . DIR)’ to force Emacs to put all backup
    | files in the directory dir'.<br />—-

  14. uh, did you read the post? that’s what it does. the big extra chunk of elisp at the beginning is for autosave files, not backups.

  15. noam, david, thanks for suggesting auto-save-file-name-transforms! definitely a simpler way to do it. i’ve updated the article.

  16. Thank you for posting this information, including the 2011 update.

  17. I think you don’t want to use custom-set-variables. That’s used by customize, and it could get confused if it sees two of them. I like the solution at http://stackoverflow.com/questions/2020941/emacs-newbie-how-can-i-hide-the-buffer-files-that-emacs-creates better:

    (defvar backup-dir (expand-file-name “~/.emacs.d/backup/”))
    (defvar autosave-dir (expand-file-name “~/.emacs.d/autosave/”))
    (setq backup-directory-alist (list (cons “.” backup-dir)))
    (setq auto-save-list-file-prefix autosave-dir)
    (setq auto-save-file-name-transforms `((“.
    ” ,autosave-dir t)))

    I like the tip about creating the directories, though.

  18. Just another thank you note.
    this is a very annoying problem.
    and your solution is simple and nice.

  19. Thank you!!! Worked perfectly! You just removed a huge annoyance!

  20. Pingback: Ondiz

  21. Pingback: Ondiz

Leave a Reply

Your email address will not be published. Required fields are marked *