<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Atomized &#187; grep</title>
	<atom:link href="http://atomized.org/tag/grep/feed/" rel="self" type="application/rss+xml" />
	<link>http://atomized.org</link>
	<description>Fragmenting reality.</description>
	<lastBuildDate>Mon, 23 May 2011 23:46:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Emacs Nerdery: Search &amp; replace across files</title>
		<link>http://atomized.org/2009/05/emacs-nerdery-search-replace-across-files/</link>
		<comments>http://atomized.org/2009/05/emacs-nerdery-search-replace-across-files/#comments</comments>
		<pubDate>Thu, 07 May 2009 18:12:21 +0000</pubDate>
		<dc:creator>Ian</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[dired]]></category>
		<category><![CDATA[emacs]]></category>
		<category><![CDATA[find]]></category>
		<category><![CDATA[grep]]></category>
		<category><![CDATA[query-replace]]></category>

		<guid isPermaLink="false">http://atomized.org/?p=560</guid>
		<description><![CDATA[Whenever I encounter a problem that’s painful to solve, I consider finding a better way to do it. This involves weighing how long I think it might take to find (or create) a better solution versus the amount of time it would take to suck it up and do it the hard way. Where this [...]]]></description>
			<content:encoded><![CDATA[<p>Whenever I encounter a problem that’s painful to solve, I consider finding a better way to do it. This involves weighing how long I think it might take to find (or create) a better solution versus the amount of time it would take to suck it up and do it the hard way. Where this fails is with painful processes encountered infrequently; since they don’t happen often, it’s less worthwhile to invest the time to improve it.</p>
<p>Multi-file search and replace is a perfect example of this kind of infrequently painful process. After messing around with for loops and sed in the shell, I finally sucked it up and got familiar with the Emacs way of doing it. It’s a great example of the synergy of Emacs tools, since it combines familiar features in a new way.</p>
<h3>Search and replace in a single file</h3>
<p>The facility for one-file S&amp;R is called <em>query-replace</em>, and it’s bound to <code>M-%</code> (plain strings) and <code>C-M-%</code> (regexes) by default. As you’d expect, it prompts for search and replacement text, then replaces it in your buffer. When using regular expressions, you have the full power of them, with the ability to capture sub-expressions and use them in your replacement.</p>
<h3>Directory editing</h3>
<p>Dired is the Emacs file management package, and it’s quite powerful. You can invoke it with <code>C-x d</code>, or by pointing <code>find-file</code> (<code>C-x C-f</code>) at a directory.</p>
<p>Dired lets you mark files with <code>m</code>, or files matching a regular expression with <code>% m</code>. Pressing <code>Q</code> runs <code>query-replace</code> over the contents of those files.</p>
<p>Dired only shows files in one directory, so this doesn’t work if you want to replace in files which span directories.</p>
<h3>Find with dired</h3>
<p>This can be mostly solved with <code>find-dired</code>. As the name implies, it runs <code>find</code>, putting the results in a dired buffer. Once you have that, you can use <code>Q</code> to S&amp;R in the matched files.</p>
<p>This is good if you need to replace a string in every file under a subdirectory, or in every file whose name matches a pattern. Where it fails is when you need to replace a string in files which contain that string.</p>
<h3>Grep</h3>
<p>Emacs has excellent integration with grep, in several flavors:</p>
<ul>
<li><code>grep</code>. Basic grepping, with results placed in <code>*grep*</code>. The buffer shows filenames, line numbers, and the content from the file which matched.</li>
<li><code>rgrep</code>. My favorite, <code>rgrep</code> performs a recursive grep and filters out unwanted files, such as backups, stuff in <code>.svn</code>, etc.</li>
<li><code>lgrep</code>. Just like <code>rgrep</code>, but not recursive.</li>
<li><code>find-grep</code>. Getting close to what we want, <code>find-grep</code> runs grep on files located with <code>find</code>. And finally…</li>
<li><code>find-grep-dired</code>. Just like <code>find-grep</code>, but puts the results in a dired buffer instead.</li>
</ul>
<p>As you’ve no doubt figured out, we’ll be using <code>find-grep-dired</code> for this task.</p>
<h2>Putting it together</h2>
<p>Now we have all the pieces, let’s put them together. As an example, let’s say that we renamed an exception and need to change the <code>catch</code> blocks in every <code>.php</code> file in package.</p>
<p>We start by running <code>find-grep-dired</code>:</p>
<pre>M-x find-grep-dired RET catch (FooException RET</pre>
<p>This gives us a buffer of files containing <code>catch (FooException</code>. It includes stuff in <code>.svn</code>; we only want <code>.php</code> files, so we can mark those:</p>
<pre>% m .php$ RET</pre>
<p>Now that they’re marked, run <code>query-replace</code> on them:</p>
<pre>Q catch (FooException RET catch (BarException RET</pre>
<p>At this point, Emacs will cycle through every match in every file and ask you to confirm the replacement. If you press <code>!</code>, it will replace the rest of the matches in the current file, and start prompting you for the next; <code>Y</code> will replace every match in every file with no further prompting. Then you’ll need to save the files:</p>
<pre>C-x s</pre>
<p>This saves every modified file at once, and we’re done.</p>
]]></content:encoded>
			<wfw:commentRss>http://atomized.org/2009/05/emacs-nerdery-search-replace-across-files/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>The thing I hate about MacPorts</title>
		<link>http://atomized.org/2008/09/the-thing-i-hate-about-macports/</link>
		<comments>http://atomized.org/2008/09/the-thing-i-hate-about-macports/#comments</comments>
		<pubDate>Thu, 25 Sep 2008 23:56:19 +0000</pubDate>
		<dc:creator>Ian</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[ack]]></category>
		<category><![CDATA[grep]]></category>
		<category><![CDATA[gripe]]></category>
		<category><![CDATA[macports]]></category>
		<category><![CDATA[subversion]]></category>

		<guid isPermaLink="false">http://atomized.org/?p=341</guid>
		<description><![CDATA[Everything exists in a bubble. There’s very little integration with the stock system. Example: I wanted to install ack, since I’m sick of getting .svn directories in my grep results. I see it’s in MacPorts, so I happily run sudo port install p5-app-ack. Unfortunately, this begins installing the perl5.8 port. Why is this thing compiling [...]]]></description>
			<content:encoded><![CDATA[<p>Everything exists in a bubble. There’s very little integration with the stock system.</p>
<p>Example: I wanted to install <a href="http://www.google.com/url?sa=U&#038;start=1&#038;q=http://petdance.com/ack/&#038;usg=AFQjCNHuyakLAzSQIuhYEZJdWuUkr3a7Tw">ack</a>, since I’m sick of getting <code>.svn</code> directories in my grep results. I see it’s in MacPorts, so I happily run <code>sudo port install p5-app-ack</code>.</p>
<p>Unfortunately, this begins installing the perl5.8 port. Why is this thing compiling Perl? OS X 10.5 ships with Perl 5.8. I need another copy… why? Does this seem <i>terrible to anyone else? Ack is all of 23kb &#8211; do I really</i> need a whole new Perl to run it?</p>
<p>Fortunately, OS X also ships with CPAN, which happily installed ack for me.</p>
]]></content:encoded>
			<wfw:commentRss>http://atomized.org/2008/09/the-thing-i-hate-about-macports/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

