That is, if I have


I would like


I'm aware that there are many OS-specific solutions to this, but I'd like to stick to elisp, ideally :).


You could just use the find tool.

M-! find . -empty -type d -delete return

Here it is wrapped in a function that confirms the delete:

(defun delete-empty-dirs ()
  (let ((dirs (split-string (shell-command-to-string "find -X $(pwd) -empty -type d") "[ \n]" t)))
    (when (yes-or-no-p (format "Delete %d empty directories? " (length dirs)))
      (with-temp-buffer (shell-command "find -X $(pwd) -empty -type d -delete")))))
  • Lovely on *nix, but Windows (et al.) don't have a find command. There's always Cygwin for those how are allowed to install it, but it doesn't come default. May 6 '15 at 19:12
  • 1
    Make your life easier on windows with: mingw.org
    – InHarmsWay
    May 7 '15 at 22:49
  • @InHarmsWay I have Cygwin actually, after trying MinGW and finding it insufficient. …Cygwin is also insufficient. :( May 8 '15 at 0:15
  • 1
    @SeanAllred Perhaps it's Windows that's insufficient. 😊 I was happy enough to find Mingw had a decent find and grep, and other basic commands. But yes, it's all more painful than it should be.
    – InHarmsWay
    May 9 '15 at 4:03

This requires the following functions from f.el, available from MELPA:

  • f-directories returns a list of directories in the given directory
  • f-entries returns all files and folders in the given directory
(defun *-delete-empty-directories (root-directory)
  "Recursively delete empty directories in ROOT-DIRECTORY.

When called from dired, `dired-current-directory' is used for

  ;; Interface
  (interactive (list (if (eq major-mode 'dired-mode)
                         (expand-file-name (dired-current-directory))
                       (read-from-minibuffer "Root directory: "))))
  (when (or (null root-directory) (string= "" root-directory))
    (user-error "No root directory provided"))
  (when (called-interactively-p 'interactive)
    (unless (yes-or-no-p (format "Delete all non-empty directories in `%s'? "
      (user-error "Directory `%s' has been left untouched" root-directory)))

  ;; Implementation
  (require 'f)
  (let ((entries (f-directories root-directory)))
    (while entries
      (let ((curdir (car entries)))
        (when (f-directories curdir)
          (*-delete-empty-directories curdir))
        (unless (f-entries curdir)
          (delete-directory curdir)
          (message "Directory deleted: `%s'" curdir))
        (setq entries (cdr entries))))))
  • Presumably, this is the library f.el that you are requiring.
    – Drew
    May 6 '15 at 15:53
  • @Drew correct – I thought it was sortof common knowledge to look for foo.el when foo is required (like \usepackage{foo} needs foo.sty in LaTeX). May 6 '15 at 16:48
  • @Drew Edited for clarity :) May 6 '15 at 17:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.