Emacs 28 Edition is out now!


Working with multiple files in dired

If you want to work on files across directories on the command line, you reach for find and xargs. But if you want to use Emacs, then you'll have to use Emacs's dired wrapper around find.
Updated for Emacs 28
16 comments

It’s all too common: you have a large swathe of files and you want to do something to them. Unfortunately, they’re not in the same directory. If you’re a command line superstar you’re going to reach for find and maybe a little xargs.

But what if you want to use Emacs?

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. Job done.

But what about the too-common case when they’re not.

Surprisingly, it is actually 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.)

Emacs is a text editor, so it’s not surprise at all that Emacs would co-opt the output from a command line ls; enrich it with hyperlinks and colors; and then call it a day. In fact, it’s such a fundamental part of Emacs that I’ve written about why Emacs has buffers.

Dired’s nothing more than ls and a large corpus of commands that operate on that output. But if that’s the case, then surely it’d work just fine if you fed it output that looks like ls but actually contains nested or relative paths, right? Right!

And don’t forget that Emacs and dired is a capable find & xargs replacement also. To say nothing of using editable dired buffers!

The Find Dired library

The command find-dired calls find to find and match files and ls to format them so dired can understand it. It’s pretty bare-bones and it’s aimed at people who want to tweak every parameter that goes into those commands.

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. find is by its nature recursive, so I don’t have to do much more than point it at a base directory.

You can control how Emacs finds matches by customizing find-ls-option. You may want to do that if you have strong opinions about the ordering or the results.

Here’s an example that uses human-readable file sizes instead of the default.

(require 'find-dired)
(setq find-ls-option '("-exec ls -ldh {} +" . "-ldh"))

Modern versions of find support the -ls argument. There’s no need to specifically invoke -exec ls if you don’t want to.

The Find Lisp library

The Find Lisp library is similar to the Find Dired library, but instead of calling out to find, the find lisp library emulates a basic version of 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 usually very fast, and it does not require the presence of tools like find. That’s mostly of note to Windows users or if you’re on minimalist platforms that may lack find.

To find stuff with find lisp type find-lisp-find-dired. To see only directories use find-lisp-find-dired-subdirectories.

Virtual Dired

Now I know what you’re thinking: can’t I just… stuff the output of ls -l in a buffer and run M-x dired-mode on it?

No.

I wish you could, but annoyingly you can’t. You have to use another command called dired-virtual and for it to work, you have to import a library that is not normally loaded in Emacs:

(require 'dired-x)

It’s called dired-x. It’s got a number of other surprises in it, but dired-virtual is one of the more important ones.

To use it, insert a long listing from ls into a buffer and type M-x dired-virtual. It’ll ask you for a base directory, so make sure it reflects the relative paths of the files you’re inserting!

Inserting Sub-Directories

Another approach is typing i on a directory in dired. It’s a neat feature, but of course a bit manual.

Final Thoughts

Combining find & friends to turn a glob-style query into a full-fledged dired buffer is a bit of a super power. It’s therefore a viable alternative to using the command line directly, as you can unleash the full power of Emacs and dired.

And if that fails, you can always use M-x virtual-dired or simply insert the sub directories manually with i.

Further Reading

Have you read my Reading Guide yet? It's a curated guide to most of my articles, and I guarantee you'll learn something whether you're a beginner or an expert. And why not check out my book?

Subscribe to the Mastering Emacs newsletter

I write infrequently, so go on — sign up and receive an e-mail when I write new articles

Copyright 2010-24 Mickey Petersen. Terms & Privacy Policy (Last updated 2022-05-24.)