Working with multiple files in dired

Here’s another frequent workflow question that needs answering:

How do you work on/with multiple files in bulk, and what if the files you want to edit are split over multiple directories?

The simplest solution, when the files are all in the same directory, is to use M-x dired (C-x d) and mark the files you want to work on. I’ll wax lyrical about dired’s amazing features in another article, so I’ll just talk about working with files en masse today.

So working with files in a single directory is nice and easy, but what if the files you want to change are not in the same directory?

Surprisingly, it is actually very, very simple. Dired works by querying ls (or an emulated equivalent if it is not available) and formatting the printed output from ls. In fact, the GNU version of ls comes with a switch -D specifically designed to format the output to suit dired (though it’s not used in newer Emacsen.)

Now that you know how dired works, it’s not such a far stretch to imagine that dired is capable of acting on any number of files, regardless of where they are on your filesystem – provided dired knows where they are, of course.

The GNU Toolchain

A lot of the external commands invoked in Emacs will involve the GNU CoreUtils, FileUtils and FindUtils packages (ls, find, mv, cp, etc.) so if you’re on Windows make sure you install the Win32 ports of the previously mentioned packages as a lot of stuff in Emacs won’t work without it.

If you’re on a platform where you don’t have GNU CoreUtils (or a commercial equivalent) then there is some hope, as an elisp version is available.

The Find Dired library

The command find-dired will use find to match the files and ls to format them so dired can understand it. It’s pretty bare-bones and it lets you change the syntax for find to suit your immediate needs.

Generally, though, I find find-name-dired to be more useful for day-to-day use when all I want is to feed it a single string to match against.

By default Emacs will pass -exec to find and that makes it very slow. It is better to collate the matches and then use xargs to run the command. To do this instead add this to your .emacs:

(require 'find-dired)
(setq find-ls-option '("-print0 | xargs -0 ls -ld" . "-ld"))

The Find Lisp library

The Find Lisp library is very similar to the Find Dired library, but instead of calling out to the external find tool, the the find lisp library emulates a very basic find in elisp.

The find lisp library uses Emacs’s regular expression engine and that means you cannot use wildcards like *.foo; instead, you have to write \.foo$. That may or may not be an issue for you, but it is worth keeping in mind.

One advantage the find lisp library does have is that it is very fast compared to find dired (though it will not run asynchronously like calling out to find would.)

To find stuff with find lisp type find-lisp-find-dired. To see only directories use find-lisp-find-dired-subdirectories. Yeah. Quite a mouthful.

Final Thoughts

I haven’t covered the deeper points of dired, but I hope to do that soon enough; dired is a complex beast and it has an incredible amount of features that, when combined with elisp and Emacs itself, makes it the best file manager in the world.