Trash File from Emacs with Put-Back Enabled on macOS
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-trash
is defined, call it withFILENAME
as an argument.Otherwise, if
trash-directory
is non-nil, moveFILENAME
to that directory.Otherwise, trash
FILENAME
using 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.
References: