search and replace in files






I always try to do more things from within emacs; as said before, it's all
about return on investment for all the time spent mastering emacs. One of
the things I sometimes still used a separate terminal for, was search and replace of text in files – a quick grep or sed from the command line.






source code: tags




If you're searching (not replacing) symbols in source code, the most
convenient way is to use a tagfile. A while ago, I discussed
navigating through source code using tags (using
GNU Global). I still often see people
writing code in emacs, and then opening a terminal open to grep for function
names, definition and so on… There is really no need for that; see the
linked entry.



The GNU Global tagfile system unfortunately does not have a search-and-replace
function; if you are using etags, however, you can use M-x tags-query-replace to replace the symbols in all files in the tagfile.



GNU Global users can of course still use the other search-and-replace
mechanisms below.








other files: rgrep




For searching recursively for some strings (regexps) in a file tree, there is
the very useful M-x rgrep. It will ask what you want to search for, some
pattern for the files to match, and the top of the directory to search.



So, for example, if you want to find all occurences of the string 'FIXME' in
txt-files in your ~/Documents directory tree, you would do something like:





M-x rgrep
FIXME
*.txt
~/Documents





and you will get at buffer with all matches. For this, it uses the same kind
of buffer you use for compilation, and you can jump to the matching locations
just like you can jump to error locations in the compilation output - that is
why with M-x next-error you can jump from match to match, even though of
course they are not really errors. The default shortcut for next-error is
C-x`, but you can of course remap that to something saner, exempli gratia:





(global-set-key (kbd "<M-prior>") 'previous-error)
(global-set-key (kbd "<M-next>") 'next-error)






so you can use M- with PgUp/PgDown to jump through the matches (or
errors).



One final comment about rgrep: in the above example, the FIXME is a
regular expression (as discussed in

building regular expressions, while the *.txt is a shell pattern (see e.g.
the findutils manual).







replacing: dired





If you want to replace text in multiple files, your best bet is to use
dired, the emacs file manager.



dired deserves its own entry (and probably more than one), but if we just
look at search-replace, the steps are not too hard. Suppose we want to replace
all strings FOO with BAR in a bunch of files in ~/myfiles/. We open

dired with C-x d, enter ~/myfiles, and a list of the files in that
directory appears.



Now, we mark the files we'd like to change by moving the cursor to them and
press m (unmark with u). You can also mark filenames matching some regexp
with M-x dired-mark-files-regexp (or '* %', obviously) or files

containing some regexp with M-x dired-mark-files-containing-regexp (or '* g').



After marking some files, you can use M-x dired-do-query-replace-regexp to
interactively replace some regular expression in all of them – you have to
press 'y' to confirm the changes. You can quit this process by pressing
'q'.



dired can even work recursively, as an anonymous commenter remarked
(thanks!); slightly edited:
You can type 'i' to insert a subdirectory to the dired buffer. You can also
run M-x find-name-dired or M-x find-dired to generate a dired buffer
with the results of the find-command. Then you can mark wanted files and
perform query replace with 'Q'. Also see: Emacs Nerdery: Search & replace across files.




As an alternative, you can use an external package like FindR for recursive
search & replace. I haven't used that one myself though, as I haven't had the
need yet.



No comments:

Post a Comment

Followers

Popular Posts