Skip to content

Working with multiple files in dired

by mickey on March 25th, 2011

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:

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.

  1. Aaron Hawley permalink

    “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.”

    Assuming you don’t need all the features of find, `C-u C-x d R RET’ will list a directory recursively by using the -R option of ls, making it pretty efficient.

  2. Sue D. Nymme permalink

    I have often wondered if there’s a way to get the file listings in dired to use commas (digit grouping) in the file sizes. I often deal with directories full of multi-megabyte-sized files, and digit grouping would be a huge visual aid. Know of anything like that?

    • mickey permalink

      Yep, of course you can :)

      Put this in your .emacs:

      (setq dired-listing-switches "-alh")

      What this does is tell dired to call ls with the extra switch -h to print file sizes in a human readable format.

      • Sue D. Nymme permalink

        That doesn’t help much, I’m afraid. For one thing, I want exact file sizes, not “14k”. For another, it makes all the file sizes between 1 and 4 characters, which obfuscates the scale (imho).
        I’d really prefer to see file sizes written out in full, but with commas. I don’t think ls has a flag to do that. I should look at the guts of dired to see how it lays out the results from ls.

  3. Jürgen Hötzel permalink

    GNU Findutils can also exec a command on multiple files (no need for xargs):

    (setq find-ls-option '("-exec ls -ld {} \\+" . "-ld"))

    • mickey permalink

      Yes, and that is the default option. But as I mentioned in the article it is also a lot slower.

      • Jürgen Hötzel permalink

        The “+” variant of the “exec” command executes “ls” on the whole file-list while the the default “;” variant executes “ls” for each found file.

        • mickey permalink

          A-hah! I didn’t know you could do that at all. Very good to know, Jürgen!

  4. Kenny permalink

    I have GNU coreutils installed via macports, i.e., they’re not the default tools. Somehow I doubt that emacs is using them. How can I tell, and then if necessary, force emacs to use Coreutils? Thanks!

    • mickey permalink

      I don’t know much about macs, but you need to ensure your PATH environment variable points to the macports stuff, and that it picks it before the “native” version. Another approach is to add the coreutils path to the list variable exec-path.

      • Kenny permalink

        exec-path is it.
        The native tools on the mac are from BSD. So yeah, the first thing to do is install macports, then you can install GNU-anything-you-want. Then install — works wonderfully. But it doesn’t appear to recognize my PATH in .bashrc and I don’t want to mess with /etc or .login or .whatever. Thus, exec-path is just the thing I’m looking for. Thanks so much!

  5. Jay Rajput permalink

    I have been a text editing fan. I am a software developer for a decade now. I was impressed with VIM. For coding, I use VIM.

    I always like the idea of learning different things, so thought of learning emacs multiple times in my career and I failed multiple times. I tried emacs again and found your blog interesting. But the absence of search on your blog, makes me use google to find the blogs.

    Please add a search option to your blog, it at all possible.

    Also Thanks for the blog.

    • mickey permalink

      Hi Jay,

      There is a search function at the bottom of the page. It’s probably a bit too well-hidden though!

      Thanks for the feedback


Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS