Delete Empty Directories

What is It?

It is a very simple program will remove empty directories (folders) from filesystem.

Surprisingly, I have not found any inbuilt command to under either M$ Windows or GNU/Linux to clean up file systems by removing unneeded empty directories. I often have such ghosts hanging around after restructuring a project archive, whether it be my photographs or a serious piece of work. Although they don’t take up much space, they are untidy and give spurious hits in searches.

It is possible, of course, to write a program to do that in shell script or a conventional compiled programming language. Here is a simple way of doing it in Perl that works identically on Linux & M$ Win32. It should also work on Mac OS X but I have not tested that.

System Requirements

A Perl interpreter (comes as standard on Mac OS X & most Linux distributions and is available as a free add-on for M$ Win32).

The Program

use File::Find;

That’s it! That is the whole program!

It will delete (assuming that the current user has permission to of course) all empty subdirectories of the current working directory. If you want to delete those under another directory instead then either change to that directory first or replace the . with the path to the desired directory.

To save the time of copying that to a file before running it, use Perl’s lazy feature whereby one can run a whole program from a string. Simply, on the command prompt, type or paste

perl -MFile::Find -e"finddepth(sub{rmdir},'.')"

and press ‘Enter’. Job done.

How it Works

  1. perl runs the Perl interpreter.
  2. -M tells the Perl interpreter to include the following module (library).
  3. File::Find is a module containing routines, of which ‘finddepth’ is one, for searching for files & directories.
  4. -e tells the Perl interpreter to use the following string as the whole program code instead of getting a program from a named file.
  5. "". I’ve used double quotation marks instead of single ones to delimit the string because M$ Win2k Cmd shell is fussy anent that. Linux Bash shell could have used either type provided they matched.
  6. finddepth(,) is a routine that recursively searches a directory tree calling the routine that is given as its first parameter for each found entity & starting at the directory given as the second parameter. finddepthis used rather than plain find because finddepth starts with deepest part of the directory tree and therefore the program will also delete directories that only contain empty directories (because those empty directories will have been deleted before the parent directory is tested).
  7. sub{} is the routine that is called for each item found by finddepth. Because it is only called from one place, the routine has lazily been no name and simply written in the place it is called from.
  8. rmdir is the whole body of the routine. It is simply the command to delete a directory. It is very lazy written in 5 ways:
    • It does not bother with an explicit parameter because it defaults to the variable $_ into which finddepth automatically stores the file name.
    • It does not bother with the directory because finddepth automatically temporarily changes the current working directory to the one the found item is in.
    • It does not bother to check that the item is a directory rather than a file because rmdir simply fails to delete files.
    • It does not bother to check that the directory is empty because rmdir simply fails to delete non-empty directories.
    • It does not bother with a ; statement terminator because the end of the block at the immediately following } is sufficient for Perl to assume end of statement as well.
  9. '' single quotation marks are used to delimit the directory path string instead of double ones to distinguish them from those surrounding the whole program. (Alternatively ‘escaped’ double quotation marks, \"\" could have been used. The \s would have been stripped off by the command shell leaving the "s in the string to be passed to perl.
  10. . is a standard abbreviation for the current working directory.

(Good grief! That explanation was 40 times as long as the program. I do have a reputation for excessive annotation but this must be my most extreme so far.)

Disclaimers, Other Perl Scripts Etc.

Not all empty directories are junk. Some are expected to be there for use when needed (such as ‘temp’ directories) or as placeholders (e.g. for mounting removable drives over). Deleting those could cause problems. Therefore it is best to only delete all empty directories from directory trees where you know they are not needed or wanted, such as certain of your own data directories which you are sure of the format of, not directories which are used by programs behind the scenes, such as system directories.

Depending on your operating system and settings, this may not be able to delete empty directories that are currently in use by running or crashed programs or which you don’t have full permissions to. That is normal for any file or directory deleting method.

According to the Perl spec I have read, rmdir should safely not delete non-empty directories or things which are not directories at all but I don’t guarantee that it will be implemented to that spec on all versions of Perl (though it should be) so check on a non-vital directory structure first and add in a test for only empty directories if needed. Anyway, as will all file & directory manipulations, I suggest that you make a backup first. I also suggest that you don’t run it on system directories because some programs may expect certain empty directories to be there.

See my computer programs index page for more simple useful computer programs.

Appendix 1: GNU/Linux/Bash Shell Script Version

find -depth -type d -empty -exec rmdir {} \;

To delete a directory other than the current one, put it between find-depth. The script works by using the find command with options -depth to start at the deepest point, -type d to limit to directories (otherwise it prints annoying error messages), -empty (ditto) & -exec to run the rmdir subsidiary shell script on the found path {}. The confusing \; is a ; which find -exec uses to mark the end of the subsidiary script to execute (instead of the common custom of putting it in quoted string) with a \ to stop it being processed as an end of the outer script. I needed help from a friend to get that syntax correct (the error messages were rather misleading).

In more recent versions of find it can be shortened (a reader of this site pointed out to me) using the new -delete operator which will delete a directory. As -deletecauses -depth to be set as default, -depth can be omitted. The resulting short form is just:

find -type d -empty -delete

Appendix 2: GUI Alternatives

I’ve been told by a visitor to this site that there are freeware file management programs which include empty directory deleting – RED for M$ Windows and FSlint for Linux. Note that I have not personally tried either of these.

(Oddly the visitor wrote that they trusted GUI programs more than command line ones. Personally I would consider a one-line command line program more trustable because, unlike a big GUI one, it can fully & quickly checked at source code level by the user before use. There is nowhere to hide a nasty it such a minute & naked program!)

By Andrew Hardwick.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s