notes from /dev/null

by Charles Choi 최민수


Bulk Search & Replace Commands for Files and Buffers in Emacs

29 Apr 2026  Charles Choi

Emacs offers a dizzying number of commands to perform bulk operations on multiple files or buffers. These commands are quite capable and can make trivial the execution of workflows that would be heroic in other editors. Unfortunately these commands are also difficult to discover as a number of them are not featured in easily accessible menus.

This post calls attention to bulk commands related to search and replace in Emacs and how their discoverability can be improved using the Casual and Anju UI packages.

Regular Expressions

Before moving forward, let’s talk about how Emacs handles regular expression syntax in search and/or replace commands. Whenever using an Emacs command involving a regular expression (regexp), you will need to understand what kind of regexp syntax is expected. There are largely two to know:

  • Emacs
  • grep (implementation dependent)

Commands using grep-style regexps do so because they invoke the local install of the grep utility. The grep regex syntax is implementation dependent. If you use GNU grep, you can read its syntax here, which share some character classes with Emacs.

The Casual RE-Builder package is a great way to work with Emacs regexps as it provides a command to escape the regexp properly for interactive input. re-builder alone only provides a regexp that can be used in Elisp code.

Bulk Search & Replace Commands

The table below shows the different search and/or replace workflows and their associated commands.

Workflows Command Regexp Type Notes
Search regexp in files in directory rgrep grep AKA “Find in Files.” Results can be edited using writeable grep (wgrep).
Search regexp in files in project project-find-regexp grep
Search regexp in files in directory and present in Dired find-grep-dired grep
Search regexp in tagged files tags-search Emacs
Search file names matching shell pattern in directory and present in Dired find-name-dired shell
Search file names matching regexp in directory and present in Dired find-lisp-find-dired Emacs Implementation uses Emacs regexp type.
Search file names matching regexp in current directory and present in Dired casual-dired-find-dired-regexp Emacs Wrapper around find-lisp-find-dired using current directory. Available via Casual.
Query replace regexp in project files project-query-replace-regexp Emacs
Incremental search marked files with plain text dired-do-isearch For use in Dired.
Incremental search marked files with regexp dired-do-isearch-regexp Emacs For use in Dired.
Query replace regexp in marked files dired-do-query-replace-regexp Emacs For use in Dired.
Search regexp in marked files dired-do-find-regexp grep For use in Dired.
Search regexp in marked files and display first match dired-do-search Emacs For use in Dired.
Replace regexp in marked files dired-do-find-regexp-and-replace grep For use in Dired.
Incremental search marked buffers with plain text ibuffer-do-isearch For use in IBuffer.
Incremental search marked buffers with plain text with regexp ibuffer-do-isearch-regexp Emacs For use in IBuffer.
View lines which match regexp in marked buffers ibuffer-do-occur Emacs For use in IBuffer.
Query replace plain text in marked buffers ibuffer-do-query-replace For use in IBuffer.
Query replace regexp in marked buffers ibuffer-do-query-replace-regexp Emacs For use in IBuffer.

Choice of command depends on the quantity and specificity of files or buffers to work on. Both Dired and IBuffer marking allow for specific selection of files or buffers respectively.

Many of the commands in the table above are discoverable via menu using the Casual and Anju packages. Hierarchical menu categorization aids in the discovery and recognition of these commands, making them more usable.

Command UI Notes
rgrep (C-o) casual-editkit-main-tmenu › (/) Search/Replace › (g) Find in Files… Available via Casual EditKit.
rgrep (Menu-bar) Edit › Search › Search in Files… Available via Anju.
project-find-regexp (Menu-bar) Edit › Search › Search in Project Files…
tags-search (Menu-bar) Edit › Search › Search Tagged Files…
project-query-replace-regexp (Menu-bar) Edit › Replace › Replace in Project Files…
find-name-dired (C-o) casual-editkit-main-tmenu › (/) Search/Replace › (d) Files… Available via Casual EditKit.
find-grep-dired (C-o) casual-editkit-main-tmenu › (/) Search/Replace › (G) Files containing text… Available via Casual EditKit.
casual-dired-find-dired-regexp (C-o) casual-dired-tmenu › (f) Filter by name… Available via Casual Dired.
dired-do-isearch (C-o) casual-dired-tmenu › (/) Search/Replace › (C-s) I-search… Available via Casual Dired.
dired-do-isearch-regexp (C-o) casual-dired-tmenu › (/) Search/Replace › (M-s) I-search regexp… Available via Casual Dired.
dired-do-query-replace-regexp (C-o) casual-dired-tmenu › (/) Search/Replace › (r) Query regexp and replace… Available via Casual Dired.
dired-do-find-regexp (C-o) casual-dired-tmenu › (/) Search/Replace › (g) Find regex… Available via Casual Dired.
dired-do-search (C-o) casual-dired-tmenu › (/) Search/Replace › (s) Search first regexp match… Available via Casual Dired.
dired-do-find-regexp-and-replace (C-o) casual-dired-tmenu › (/) Search/Replace › (G) Find regex and replace… Available via Casual Dired.
ibuffer-do-isearch (C-o) casual-ibuffer-tmenu › (C-s) I-Search… Available via Casual IBuffer.
ibuffer-do-isearch-regexp (C-o) casual-ibuffer-tmenu › (C-M-s) I-Search Regexp… Available via Casual IBuffer.
ibuffer-do-occur (C-o) casual-ibuffer-tmenu › (O) Occur… Available via Casual IBuffer.
ibuffer-do-query-replace (C-o) casual-ibuffer-tmenu › (M-r) Query Replace… Available via Casual IBuffer.
ibuffer-do-query-replace-regexp (C-o) casual-ibuffer-tmenu › (C-M-r) Query Replace Regexp… Available via Casual IBuffer.

Refactoring Guidance

The replace commands can do catastrophic damage if not used with caution. Treat them like power tools.

Some guidance before using replace commands:

  1. Have a backup plan in case you need to recover anything.

  2. Use re-builder to help figure out the right regexp.

  3. Know the scope of what you want to change (directory, files, buffers).

  4. Some commands will only modify the buffer of an affected file. Check if modified buffers are saved. You can use IBuffer to identify and save such buffers. It is left as an exercise to the reader to determine which commands exhibit this behavior.

Closing Thoughts

The inventory of commands above are from what I know of Emacs, which is guaranteed to not be comprehensive. If there are others missing from this list, please let me know at kickingvegas@gmail.com.

While many of these commands have been in Emacs for years (decades even), they were not usable to me until I built a UI for them. I think motivated readers using Casual and Anju for bulk search and/or replace tasks will find a similar sentiment.

emacs

 

AboutMastodonBlueskyGitHub

Feeds & Tags
Get Scrim for macOSGet Captee for macOS

Powered by Pelican