Cleandesk.el is a collection of functions to rapidly rename and process files in Dired.
Pictures, PDFs and many other kinds of files frequently end up on my Desktop. In the past, I used Hazel and/or Devonthink to automatically rename and refile these files. Cleandesk offers an alternative (manual) approach for these tasks from within Emacs. It also allows to quickly change directories or search files. Cleandesk draws on Dired, fd (and tree for cleandesk-show-tree
).
To be sure, vanilla Dired probably can do most of this. But perhaps neither as convenient nor as swift. I still use Cleandesk daily (January 2025).
0.5.2
- Added options to manually set
cleandesk-data-folders
and to specify location of the dotfile; improved documentation
0.5.1
0.5
- Added
cleandesk-show-tree
0.4.1
- Some fixes +
cleandesk-create-org-link
andcleandesk-create-org-link-inline-image
0.4
- Added
cleandesk-simple-rename
, see Rename below
Clone the repository:
git clone https://github.com/rtrppl/cleandesk
To run Cleandesk, you need to load the package by adding it to your .emacs or init.el:
(load "/path/to/cleandesk/cleandesk.el") ; You actually only need cleandesk.el
If your inbox folder is not the Desktop, you need to tell Cleandesk:
(setq cleandesk-inbox-folder "~/path/to/inbox")
In order to use Cleandesk you’ll want fd installed on your machine. The easiest way to do so might be homebrew, i.e. brew install fd
. fd
is much (!) faster than find
but if you prefer find
, you need to set this:
(setq cleandesk-search-tool "find") ; standard is fd
If you want to use cleandesk-show-tree you also need tree. Again, an easy way to install it is homebrew, e.g. brew install tree
.
These are the “parent” directories of the folders you want to jump to or move files into. For autocompletion, Cleandesk will only consider directories that are on this list (and their sub-directories). A typical candidate might be “~/Documents”. There a two ways to specify these folders:
- The first time you use
cleandesk-jump-to-folder
orcleandesk-move-files
it will ask you to add a Cleandesk folder. A JSON list of these folders is stored in a file and the functionscleandesk-add-folder
andcleandesk-remove-folder
modify this file. The location of this file is stored incleandesk-dotfile
, the default is~/.cleandesk-directory-list
. To modify location and/or name of this dotfile:
(setq cleandesk-dotfile "~/some/folder/.cleandesk-directory-list")
- An alternative way to set the list of Cleandesk folders is to modify
cleandesk-data-folders
manually:
(setq cleandesk-data-folders '("~/Documents/Some/Folder" "/Users/some/user/projects"))
Remember that only the main “parent” directories need to be specified. If cleandesk-data-folders
is set manually, the functions cleandesk-add-folder
and cleandesk-remove-folder
cannot be used.
The date-string used by cleandesk-prepend-date
and cleandesk-rename
can be set via:
(setq date-string "%Y_%m_%d-%H%M%S-") ; this is the default Cleandesk date-string
Finally, you may also want to set keybindings for the main functions (I have bound the Mac-Command Key to super/s):
(global-set-key (kbd "M-s-u") 'cleandesk-open-inbox)
(with-eval-after-load 'dired
(define-key dired-mode-map (kbd "J") 'cleandesk-jump-to-folder)
(define-key dired-mode-map (kbd "M") 'cleandesk-move-files)
(define-key dired-mode-map (kbd "z") 'cleandesk-prepend-date)
(define-key dired-mode-map (kbd "r") 'cleandesk-rename)
(define-key dired-mode-map (kbd "S") 'cleandesk-search) ;; see cleandesk-search
(define-key dired-mode-map (kbd "R") 'cleandesk-simple-rename) ;; replaces dired-do-rename; see cleandesk-simple-rename for more
(define-key dired-mode-map (kbd "T") 'cleandesk-show-tree))
This is my current setup:
(use-package cleandesk
:straight (:host github :repo "rtrppl/cleandesk"
:branch "main")
:config
(setq cleandesk-inbox-folder "~/Desktop")
:bind
(:map global-map
("M-s-u" . cleandesk-open-inbox)
("M-s-j" . cleandesk-jump-to-folder))
(:map dired-mode-map
("J" . cleandesk-jump-to-folder)
("M" . cleandesk-move-files)
("z" . cleandesk-prepend-date)
("S" . cleandesk-search)
("R" . cleandesk-simple-rename)
("b" . cleandesk-create-org-link)
("T" . cleandesk-show-tree)
("r" . cleandesk-rename)))
To quickly go to the Cleandesk inbox invoke M-x cleandesk-open-inbox
(or the keybinding you have set). This will open a new Dired buffer showing the Cleandesk inbox. For me this is the Desktop.
cleandesk-jump-to-folder
allows you to jump to a Cleandesk directory or any of its sub-directories in Dired using a completion framework. While it was primarily intended for use in Dired, the function can be invoked from anywhere. If no Cleandesk directory is defined, the user is urged to add a directory as a Cleandesk directory (via cleandesk-add-folder
).
This function and cleandesk-move-files
are using fd, which can rapidly process 1000s of directories. To give you an idea: In my setup, Cleandesk operates with more than 5000 directories and there is no noticeable delay when preparing the list of directories for completion!
cleandesk-prepend-date
prepends the creation date of the file to the filename. If multiple files are marked in Dired, the date-string will be prepended to all of them.
cleandesk-rename
prepends the creation date and also renames the file itself (but does not change the file extension). This also works across all marked files in Dired. cleandesk-simple-rename
is a simple replacement function for dired-do-rename
, which does have some issues when using it with ivy or Vertico (at least for me). The function also takes the existing filename as basis for the rename, speeding up the process.
cleandesk-move-files
moves all marked files to a chosen Cleandesk directory or one of its sub-directories (selected via a completing framework such as Helm or Vertico).
cleandesk-search
uses the macOS Spotlight feature to search for a specific term in all files in the current directory. If called with C-u, search expands to all Cleandesk folders. There does not seem to be a good open-source/platform-independent alternative that is capable of searching within .pdf or .docx files (that I know of). Despite this, I have added ripgrep-all (which is promising for PDFs and some other types of documents but very slow) and ripgrep as options. In your init.el you would need to add:
(setq cleandesk-search-tool "rga") ;; for ripgrep-all or "rg" for ripgrep
cleandesk-show-tree
combines the output of tree
and fd
to create an Orgmode buffer showing a tree of folders for the currently visited Dired folder. Every folder name is linked (see screenshot above). Use n, p to navigate, o to open a folder in Dired, O to open it using the system default (this uses org-open-at-point
), and q for exit.
cleandesk-add-folder
adds folders to the list of Cleandesk folders, cleandesk-remove-folder
will remove a folder from said list.