14

I'd like to define a set of files within which I can search and replace text.

To clarify:

I would like to be able to search, e.g., in all files xk*.tex in a given directory (and excluding backup files). I would also like to be able to change the expression, e.g., "uncertainty", to "indeterminacy" in all files dd*.sh and ee*.cls .

What is the standard way to do this?

Dan
  • 32,584
  • 6
  • 98
  • 168
Claudio
  • 141
  • 1
  • 3
  • @Claudio You might want to take a look at `dired` for doing find and replace over a subset of files in a given directory. – Squidly Feb 23 '15 at 12:48
  • [Here's an example](http://emacs.stackexchange.com/a/243/115) of doing "search/replace" in multiple files in a directory/project using `ag`, `wgrep` and `multiple-cursors`. – Kaushal Modi Sep 29 '15 at 02:30
  • `helm-ag` works great for this. https://yamadapc.github.io/posts/emacs/workflow/2015/03/11/using-helm-ag.html – Chris Stryczynski Oct 11 '21 at 15:42

5 Answers5

5

You can use M-x find-name-dired to get a dired buffer containing links to all files matching a given name pattern.

Use M-x find-grep-dired to get a dired buffer containing those files whose contents match the provided grep pattern.

There are many more such commands; which is most appropriate depends on your requirements, so please consider updating your question.

Then you can traverse the list of files using macros. Take a look at Brian's answer for an example: https://emacs.stackexchange.com/a/9497/2005

5

If all of the files are in the same directory, you could follow these steps. I'll base this on the second example given in the comments:

  1. M-xdired to open the relevant directory in dired mode.
  2. %m to run dired-mark-files-regexp in that directory.
  3. Enter ^dd.*\.sh$, which is the regexp equivalent to dd*.sh. Those files will now be marked with a *, and may also appear highlighted in a different color depending on your color scheme.
  4. Repeat step #3 as many times as needed, with whatever regexp you want (e.g. ^ee.*\.cls$) until all the files you want to edit are marked.
  5. Q to run dired-do-query-replace-regexp on the files you marked.
  6. Enter uncertainty and indeterminacy as the query strings. (I think this will be case-sensitive. If you need it to be case insensitive, that may require a regexp, but I'm not sure.)

And that's the idea. If you need to repeat this a few times in different folders, you can record steps 2-6 as a macro (press C-x ( after step #1, and C-x ) after step #6). And even if you're not very comfortable with elisp, you could translate that macro into elisp using insert-kbd-macro and try to hack it into a useful function.

nanny
  • 5,704
  • 18
  • 38
Brian Z
  • 2,863
  • 16
  • 22
  • 1
    Please note that in Emacsland, `S-q` does not mean `shift+q`, it means `super+q`. You should just write `Q` if you mean `shift+q`. I edited your comment to reflect this. – nanny Feb 23 '15 at 17:11
  • 5
    Actually no, `S-q` does mean `shift+q`; `super+q` would be written `s-q`. – Sue D. Nymme Feb 23 '15 at 18:09
5

If you're working on a well-defined project, you can use occur and grep facilities within that project via projectile. Cribbing from its github description, among the various bits of functionality offered by projectile, it can do:

  • replace in project
  • multi-occur in project buffers
  • grep in project
  • visit project in dired
Dan
  • 32,584
  • 6
  • 98
  • 168
5

Use rgrep and wgrep.

With rgrep you can search all for a regexp in files which filename match a regexp and inside a directory (and its subdirs)

with wgrep you can edit the buffer containing the results of your rgrep search.

PuercoPop
  • 396
  • 2
  • 11
4

Using rgrep and wgrep:

  1. M-xrgrep.
  2. Enter the regex to search for.
  3. Enter the glob pattern matching which files to search in.
  4. Select the base directory to search in.
  5. Results will be shown in a grep buffer.
  6. C-cC-p or M-xwgrep-change-to-wgrep-mode to make the grep buffer writable.
  7. Use your preferred method for search and replace within a buffer. I'm an evil user, so would use
    :%s/<text to replace>/<replacement>/g.
  8. Save the buffer to save the changes to all files.
glennsl
  • 141
  • 2