Recursively delete empty directories in Windows

100

44

I have a directory on my Windows 7 machine that has hundreds if not thousands of sub-directories. Some of them have files, some do not. I want to delete all the empty directories.

Looking at the del and rmdir DOS command, it does not look like you can recursively do this without deleting all the files. Is there a way to do this from the command line?

mohlsen

Posted 2009-09-11T13:38:58.557

Reputation: 1 172

1It can be done easily using ROBOCOPY. See my answer below for details. – Varun Sharma – 2015-10-16T18:48:40.573

I am amazed there's no simple answer to this question. – billpg – 2012-04-05T12:45:57.697

@billpg: simple as it could get: xcopy FROMDIR TODIR /s. See this SO answer: http://stackoverflow.com/a/14742810

– eckes – 2013-03-20T07:42:21.133

1XCOPY deletes directories? – billpg – 2013-03-20T11:24:32.040

Answers

121

You can use Remove Empty Directories utility.

Alternatively you can use this one-liner batch file (from DownloadSquad):

for /f "delims=" %d in ('dir /s /b /ad ^| sort /r') do rd "%d"

(if used inside a batch file, replace %d with %%d)

This works because rd will not remove a directory that contains files.

caliban

Posted 2009-09-11T13:38:58.557

Reputation: 18 979

This doesn't work if the folder is set to read only. – shinzou – 2015-07-19T22:14:42.140

1

Look at http://stackoverflow.com/a/34025977/694360 to find out how to add this functionality to context menu.

– mmj – 2015-12-01T17:36:05.603

The for loop command worked perfectly. – Aaron Reed – 2016-03-01T02:22:49.083

1Just a warning, this script destroys directory junctions too. I learned this the hard way. – Pyroglyph – 2016-05-22T15:56:30.237

@Pyroglyph: Can you edit the answer (I don't fully understand what this means)? – user598527 – 2017-10-13T16:25:57.133

I get this error: "sort: cannot read: /r: No such file or directory" UPDATE: Ah, my cmd is using Git-for-Windows' git\usr\bin\sort.exe instead of `system32\sort.exe). – Dai – 2020-02-19T05:29:58.597

6P.S I suggest you try the GUI-based tool first, before trying any command-line commands that can potentially delete all files. – caliban – 2009-09-11T13:50:54.560

that tool looks good. I will check it out and report back – mohlsen – 2009-09-11T14:31:28.357

Using the batch version gives me an error: The system cannot find the file dir /ad/b/s | sort /R. – EBGreen – 2009-09-11T15:58:50.240

Hang on, testing command in my Windows VM. – caliban – 2009-09-11T16:02:23.573

Also the batch version would not handle spaces in the directory names. I'm pretty sure that it would not remove a directory that contained only empty sub directories either. – EBGreen – 2009-09-11T16:06:04.923

Got it, couple of errors with the DownloadSquad's command (!!). I've amended in my answer. :) – caliban – 2009-09-11T16:13:40.243

Still won't delete a directory that contains an empty directory. – EBGreen – 2009-09-11T17:59:20.153

1Make sure it is truly empty. A hidden desktop.ini is still considered a file. same as a thumbs.db. If you want to verify whether this works, create a test directory with directories inside that are empty and populated. It works, I've verified. – caliban – 2009-09-11T18:19:51.360

1Yep. It works. My mistake. – EBGreen – 2009-09-11T18:27:33.607

9for /f %d in ('dir /s/b') do rmdir "%d" should work as rmdir cannot remove a non-empty folder – seanyboy – 2009-09-16T13:14:07.720

RED is the best tool for this, since it handles directories with nothing but junk in them (Thumbs.db, .DS_Store), lets you permanently protect directories from deletion, shows a nice tree view, etc. I got it working in Windows 7 using the compatibility troubleshooter thing. There's also a list of alternative tools at the bottom of the RED web site. – endolith – 2010-01-19T20:59:00.793

53

You can also use ROBOCOPY. It is very simple and can also be used to delete empty folders inside large hierarchy.

ROBOCOPY folder1 folder1 /S /MOVE

Here both source and destination are folder1, as you only need to delete empty folders, instead of moving other files to different folder. /S option is to skip copying(moving, in the above case) empty folders. It is also faster as the files are moved inside the same drive.

Varun Sharma

Posted 2009-09-11T13:38:58.557

Reputation: 656

1Magic. So this moves all non-empty folders to the very same location they were already in (so does nothing?), and skips empty folders? But then: why would skipping them result in deletion? And wouldn't this move nested folders into folder1? Scary, unless tested well. – Arjan – 2015-09-13T11:15:59.630

3@Arjan I have tested it, and it works perfectly!. To understand its working, its like moving all files to different location, except empty folders, and then deleting the left-behind empty-folders. /MOVE copies the files first, and then deletes the source file after copying. So, as /S is used, it copies the non-empty folders to destination(same folder in the above case). Then, it deletes the empty folders(like, its thinking that empty-folders has already been copied). No, it does not move nested folders into folder1, as ROBOCOPY moves folders recursively. – Varun Sharma – 2015-09-13T19:56:57.020

3it even works with UNC paths (at least on win7) ! Brilliant ! – Arioch 'The – 2015-10-15T14:11:03.680

Can Robocopy move files to the recycle bin? – user598527 – 2017-10-13T16:37:48.673

2This is a very elegant solution without any third-party software needed. Thank you! – Marcus Mangelsdorf – 2017-12-28T20:20:35.703

1This just did its magic and worked perfectly. Thanks! – CharleyDC5 – 2019-04-23T14:36:15.300

1Varun thanks. This is an awesome solution. Went through 3.8TB of files across 60,000 folders in about 10 minutes. Not a single file lost, but no more empty directories. Beautiful. – SimonGoldstone – 2019-08-15T10:34:40.923

Sometimes I wish I could upvote an answer 3 times. Brilliant trick! – Andreas – 2019-08-29T06:30:54.070

15

Since Cygwin comes with GNU find, you can do this:

find . -type d -empty -delete

Or to avoid the noise when a folder no longer exists:

find . -type d -empty -execdir rmdir {} +

Michael

Posted 2009-09-11T13:38:58.557

Reputation:

This can also now be done using Windows 10 Bash. – March Ho – 2017-10-07T19:06:50.433

For my install of Windows 10 this (find . -type d -empty -delete) fails from the command prompt with the following error: FIND: Parameter format not correct – ImpressTheNet Web Developer – 2018-01-04T22:39:15.010

7

The free utility EmptyFolderNuker does this fine, from a base folder of your choice. It also removes those directories only containing empty sub-directories.

Rob Kam

Posted 2009-09-11T13:38:58.557

Reputation: 1 749

1I like this over the pure command-line version as it allows you to preview the things that get deleted. You can always call it from the command-line using "%~dp0\EmptyFolderNuker.exe" %cd%. – Jeroen Wiert Pluimers – 2014-12-27T14:30:56.510

1The one-liner batch file didn't work for me (I get the error "%%d was unexpected at this time."), and the Remove Empty Directories program will not install (it says on the linked page that it is not compatible with Windows 7 anyway).

This program worked like a charm. – Phoenix – 2010-03-07T11:52:10.410

1@rob-kam The URL for "EmptyFolderNuker" isn't available anymore. – PeterCo – 2019-08-09T08:13:31.907

@PeterCo Thanks, fixed now. – Rob Kam – 2019-08-12T19:49:08.960

1As user36580 wrote below, "it is likely you are running directly from the command line. In that case, change the double %% to a single %" – Lachlan McD. – 2012-07-15T03:27:47.803

0

Combining Gareth's and G-Man's posts:

find . -depth -type d -empty -execdir rmdir {} +

Edit: But that gave a security error because of 'C' in my PATH var...so instead:

$find . -depth -type d -empty | while read dir; do (rmdir -v $dir); done

I don't use xargs because it appears to have an input line limit (of about 1024 lines, I think?), whereas

 while read x; do (command $x); done

just keeps on going for as long as it has input. Leave out the '-v' verbose flag if you don't want to see the results and/or want it to run faster.

skeetastax

Posted 2009-09-11T13:38:58.557

Reputation: 101

0

Hmmm... maybe even simpler solution:

for /d /r %d in (*.*) do rd "%d"

Start this from the folder you want empty folders to be deleted.

/d - will work on folders, not files /r - will recurse subdirs

Daniel Mošmondor

Posted 2009-09-11T13:38:58.557

Reputation: 484

0

None of the previous answers worked for me, so I made the following file:

EmptyDirectoriesRemove.cmd

Contents:

@setlocal enableextensions enabledelayedexpansion

:walk_tree
for /D %%d in (*) do (
cd %%d
@CALL :walk_tree %%d
cd ..
rd %%d
)

endlocal

Usage: Cd to the top level directory you want to clean up. From the command line prompt, run:

EmptyDirectoriesRemove.cmd

Warnings will show up for non-empty directories.

Usual disclaimers: Use at your risk. Backup before testing. etc.

Jahmic

Posted 2009-09-11T13:38:58.557

Reputation: 211

0

The 4NT shell (nowadays Take Command) has a /sx option to "DEL". /S is recursive, the appended X is remove empty dirs.

Marco van de Voort

Posted 2009-09-11T13:38:58.557

Reputation: 211

0

If you have Cygwin installed, you could do this:

find -type d -exec rmdir {} \;

Anthony Giorgio

Posted 2009-09-11T13:38:58.557

Reputation: 589

1Or use find (starting-directory) -depth -type d ....  The -depth option tells find to do something like reverse the order of the output — it goes to the deepest directory levels first, then works its way back up. – G-Man Says 'Reinstate Monica' – 2015-06-21T03:35:40.217

4Not necessarily. That might not delete directories with only empty subdirectories. You might have to reverse it.

find -type d -print0 | tac | xargs -0 rmdir
 – Ryan C. Thompson  – 2009-09-11T22:56:04.627

I never knew about "tac" before. That's really nifty! – Anthony Giorgio – 2009-09-12T01:52:50.180

0

If you're working in emacs (making this platform-agnostic), the following works:

(defun *-delete-empty-directories (root-directory)
  "Recursively delete empty directories in ROOT-DIRECTORY.

When called from dired, `dired-current-directory' is used for
ROOT-DIRECTORY."

  ;; 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'? "
                                 root-directory))
      (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)))))

Sean Allred

Posted 2009-09-11T13:38:58.557

Reputation: 910

...Please tell me you wouldn't have to type all of this in order to accomplish this in emacs. – Hashim – 2016-12-31T00:56:49.470

1@Hashim The idea is that you have it defined in your init and then bound to a key. Technically I could have it bound to D if I wanted to, but since I don't have a common need for this, all I have to type is M-x *ded RET and bam–done. (If I did indeed have to type this every time, you're absolutely right that it'd be absurd – luckily that's not the case.) – Sean Allred – 2017-01-01T07:33:39.017

Fair enough, that sounds more plausible. – Hashim – 2017-01-01T22:30:51.977

Does M-x *ded RET have any significance or is it random? If the latter, how do you keep track of all the shortcuts you've assigned in emacs? Does memorisation suffice or do you find yourself having to look them up? – Hashim – 2017-01-01T22:32:36.537

1@Hashim *ded is an abbreviation for the full function name *-delete-empty-directories. Many completion engines (such as ivy, the one I use) understand this kind of fuzzy matching. As for keeping them memorized… I simply don't have to. The functions I've defined all start with * so I can easily find them if they're not bound to a key. Otherwise, emacs itself will tell me if there was a faster way of calling the function. If all else fails, there's always apropos. – Sean Allred – 2017-01-02T02:10:21.467

Can the downvoter please describe what should be improved upon in this answer? It's a valid approach. – Sean Allred – 2019-02-07T00:00:40.700