2009-05-15

using the systems 'trash' when deleting files

A short tip today.

When you delete files and directories in Emacs 23 (say, with dired), instead of losing the files until the end of times (or at least until the singularity), you can move them to the 'trashcan', by whatever name that rose comes in your system, 'Trash' or 'Recycle Bin'…

To enable this, put the following in your .emacs:

(setq delete-by-moving-to-trash t)
There is one problem - a bug? I am using Ubuntu 9.04, which follows the Freedesktop Trash Spec; it moves delete file in ~/.local/share/Trash, together with some metadata, so it can restore the file to their original location. However, emacs follows some older convention, ie. to move the file to ~/.Trash, and without any metadata.

You can partially fix this by making ~/.Trash a symlink to ~/.local/share/Trash/files/, but of course that does not get you the metadata.

8 comments:

jfm3 said...

capture the metadata:

(setq delete-by-moving-to-trash t)
(defun system-move-file-to-trash (filename)
(shell-command (concat "gvfs-trash " filename)))

djcb said...

@jfm3: that's clever!

[ some quoting for the filename is needed though.. suppose you have a file called "foo; cd $HOME; rm -rf *" ]

Anonymous said...

Nice one. I prefer Unix "rm is serious business" semantics, but I didn't know Emacs did this, and I know people who would find it useful.

Ryan said...

How convenient that emacs provides a function for shell-quoting things. This works perfectly.

(defun system-move-file-to-trash (filename)
(shell-command (concat "gvfs-trash " (shell-quote-argument filename))))

Ryan said...

Oh, and if you don't use gvfs (part of GNOME), you can install the trash-cli package and replace "gvfs-trash" with just "trash".

Ryan said...

Hmm. Using this can cause some problems. Files outside your home directory are untrashable. In particular, files in /tmp/emacs1000/. If you use emacsclient, emacs will be unable to trash the server socket on exit, and next time you start emacs, emaceclient will not work.

To fix this, we need a trash-or-rm command:

$ cat > ~/bin/trash-or-rm.sh
#!/bin/sh

## This attempts to trash a file (or files), and then attempts to remove it if it still exists.

trash "$@" >/dev/null 2>&1
rm -f "$@"
[Control-D]

I hope this blog didn't munge any characters in that script, but I think you get the idea. Then,

(defun system-move-file-to-trash (filename)
(shell-command (concat "trash-or-rm.sh " (shell-quote-argument filename))))

Feel free to embellish the script as necessary. For example, you could manually move things to the trash if they're not too big.

Ryan said...

I've updated my solution. See EmacsWiki: http://www.emacswiki.org/emacs/SystemTrash

Anonymous said...

Please note use of the freedesktop.org trash can was added to emacs 23.2 (resolved bug #973). It was too late to make feature freeze for 23.1, but is in fact the default in CVS HEAD.