29 Apr 2026
Bulk Search & Replace Commands for Files and Buffers in Emacs
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. |
| Run git grep, searching for regexp in directory. | vc-git-grep | grep | |
| Replace all references to identifier. | xref-find-references-and-replace | ||
| Interactively replace identifier in current xref buffer. | xref-query-replace-in-results | ||
| Rename symbol at point for project. | eglot-rename | Requires Eglot support. |
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. |
| vc-git-grep | (Menu-bar) Tools › Version Control > Git grep… |
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:
-
Have a backup plan in case you need to recover anything.
-
Use
re-builderto help figure out the right regexp. -
Know the scope of what you want to change (directory, files, buffers).
-
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.
Amended 2026-04-30: Added vc-git-grep, eglot-rename, xref-find-references-and-replace, and xref-query-replace-in-results. Thanks to Henry Leach and Gene Pasquet for their input!
Past Articles
| 24 APR 2026 |
Some nice to know keybindings when using the mouse in EmacsSome keybindings to know whenever you’re working with a mouse in Emacs. read more |
| 23 APR 2026 |
Call for Testing: Scrim v1.1.3 TestFlight on pre-release Emacs 31Looking for folks who want to test a new pre-release build of Scrim v1.1.3 which fixes it for Emacs 31. read more |
| 8 APR 2026 |
Computing Days Until with EmacsCountdown clocks are always useful. Here’s one for computing days until in Emacs. read more |
| 7 APR 2026 |
Calming Mouse Interaction in DiredSingle click to open a file in Dired is too twitchy. This post shows how to change it. read more |
| 30 MAR 2026 |
Announcing AnjuAnnouncing Anju, a project to align mouse interactions in Emacs with contemporary (circa 2026) expectations. Now available on MELPA. read more |
| 3 MAR 2026 |
Casual now available on NonGNU ELPACasual is now available on NonGNU ELPA. read more |
| 19 FEB 2026 |
Announcing Casual OrgAt long last, announcing Casual support for Org Mode. read more |
| 10 FEB 2026 |
Deburring Emacs Imenu GUI ConfigurationA bit of tuning to get Imenu GUI configuration working with any derived mode from |
| 7 FEB 2026 |
Using Casual to work with Emacs Registers, Rectangles, and WindowsUse Casual to effectively use Emacs registers, rectangles, and windows on the regular. read more |
Page 1 / 18 >