I’ve enabled using the macOS system trash in Emacs to feel safer experimenting with
dired and other file manipulation functions in Emacs.
This enables using the trash by default:
(setq delete-by-moving-to-trash t)
When this is enabled,
move-file-to-trash is used to delete files. The manual reveals what’s affected, but only the function API docs from within Emacs tell the whole story (and are super hard to search online for whatever reason):
If the function
system-move-file-to-trashis defined, call it with
FILENAMEas an argument.
trash-directoryis non-nil, move
FILENAMEto that directory.
FILENAMEusing the freedesktop.org conventions, like the GNOME, KDE and XFCE desktop environments. Emacs moves files only to “home trash”, ignoring per-volume trashcans.
So by default, the
delete-by-moving-to-trash variable enablement does nothing.
Set the user-default trash path to make deletion move a file to trash:
(setq trash-directory "~/.Trash") ;; fallback for `move-file-to-trash'
With this, all files are moved into the trash, but you cannot use the macOS ‘Put Back’ functionality. I expected an extended file attribute to control this, but it’s something else, apparently. Reading the attributes of files trashed by Finder doesn’t reveal anything.
But there’s a command-line utility called
trash that can be told to use Finder’s functionality to move a file to the trash and enable put-back.
So if we revisit the function docs, it says
trash-directory is just a fall-back. The first attempt is made using the function
system-move-file-to-trash if it exists. If we declare that function, we can use it to use the
trash CLI app; and for good measure, we’ll limit it to macOS:
(when (memq window-system '(mac ns)) (defun system-move-file-to-trash (path) "Moves file at PATH to the macOS Trash according to `move-file-to-trash' convention. Relies on the command-line utility 'trash' to be installed. Get it from: <http://hasseg.org/trash/>" (shell-command (concat "trash -vF \"" path "\"" "| sed -e 's/^/Trashed: /'") nil ;; Name of output buffer "*Trash Error Buffer*")))
This just forwards the file path to the
trash CLI utility and then prepends a string to format the output;
trash -F uses the Finder trash functionality;
trash -v returns the path name of the trashed file on success; and with the
sed replacement, we get
"Trashed: /path/to/file.txt". This output is printed in the minibuffer after deletion as you see in the screenshot.