Recently I had to edit multiple files (239 in total) scattered in a bunch of directories and subdirectories. Here’s a quick and safe way to do it.
What I had to do was add the Google Analytics script snippet to a part of a website that was being maintained by a pair of <your favorite bad adjective here> developers.
So, first I thought of using sed or awk or something like that, but doing a quick search replace like that without checking if my match is correct in every instance in a bunch of files can lead to a big disaster.
But wait, I have Emacs! So, the first thing to do is find and list all the files you need to edit.
-
Open the parent directory
Use dired to open the parent directory where all the files and directories are. Open dired with:
M-x find-dired
and enter the path for the directory. -
Find the files
Emacs will then prompt: “Run find (with args):”. So if you need to edit all HTML files, or in my case, PHP files, you type:
-name "*.php"
If you want all files regardless of type, enter
-type f
Basically you can type in any arguments you want if you know how to use the find command. -
Mark the files you need to edit
A list of all found files will appear in a dired buffer. Now you need to mark the files you want to work with. Typically you’ll mark all files since you already filtered them. Press
t
to toggle marks and all files will get marked. Or if you want to hand pick them, move the cursor to the file line or name and pressm
. -
Do the find and replace
Type: Press
Q
orM-x dired-do-query-replace-regexp
to run the find and replace command. It will prompt you first for the text you want to find, then will prompt you with the text you want to replace it with.Then Emacs will start the find and replace operation, and will prompt you on every find if you want to replace the text or skip it. To replace, type
y
, to skip to the next find typen
. To replace all occurrences without asking, type!
. To cancel the operation, typeC-g
. -
Save the edited files
Now that you’ve made all these changes, you need to save the files. To avoid saving manually all files, you can open ibuffer
M-x ibuffer
Which will list all you opened files (called buffers). Now, like in dired, you need to mark the buffers you want to work with. To mark all unsaved files, type
* u
and then typeS
(that’s shift+s, for the capital letter) to save them.
Done!
Easy and without a sweat.
photo by zyphichore on Flickr.
14 replies on “Emacs tip: How to edit multiple files on several directories in less than a minute”
An even easier way to save all files (without prompting) is to invoke save-some-buffers with a prefix: C-u C-x s.
vim `find . -name ….`
:bufdo %s/replaceThis/withThat/ge | update
Or you could just C-x C-f like usual and use wildcards.
Hey! THIS IS AWESOME. I was just facing exactly the same challenge this weekend, and this is EXACTLY what I wanted.
When I need this kind of replacements I use perl with this command:
perl -p -i -e 's/SOMETHING/REPLACEMENT/' $(find . -name "*html")
Hey, this is neat. While this can be done in a variety of ways using many different tools, I surely will be trying this one out the next time I need to search-replace in multiple files — I like the fact that you can set things up to query before actually performing the replace. It’s cool to be able to use the same tool (emacs) to do multiple tasks. Great.
Nu,
I’m glad you found this tip useful. I always forget the procedure, so I decided to ppst it. Maybe I should post some more tips.
Daniel,
Thanks, but it reminds me of this little cartoon:
http://www.flickr.com/photos/rhine/2763293190/
In the find-dired example, when emacs asks you to “Run find (with args): “, you should type:
-name “*.php”
You need the quotation marks around *.php otherwise you will get an error.
Yes, as people love to point out, there are more compact ways to do a simple find and replace in a bunch of files. What’s good about this method is you are verifying the replacements. In my experience, I usually match things I don’t want to replace, and I’m pretty sure you do too, meaning finding and replacing with one line of code is a fairly irresponsible thing to do.
I’d never seen M-x find-dired before – I don’t think I’ll ever learn everything about Emacs.
[…] How to edit multiple files on several directories in less than a minute (tags: Emacs tips howto) […]
[…] Saldaña wrote about using search & replace across files in emacs. Type: M-x dired-do-query-replace-regexp to run the find and replace command. It will […]
[…] of static HTML files with lots of repeating text structures. In the past I’ve talked about editing multiple files with Emacs. This approach works very well when the number of multiple files and text matches in each file is […]