{ |one, step, back| } 1 of 1 article Syndicate: full/short

Using Rake as a Library -- Update   31 Aug 06
[ print link all ]

Why Not Find?

Why Not Find?

After posting FindInCode, someone legitimately asks: “Why not just use Find?”

Good question! Find is a Ruby supplied module to recursively search directories. So why not use it instead of Rake. Then your script won’t have a dependency on Rake.

Well, in short:

  1. Rake provides two functions, recursive directory searching and line by line searching (note that egrep is a FileList method provided by Rake, and is not the same as the grep method provide by Ruby arrays). Find only handles the directory search thing.
  2. I almost never use a Ruby installation without Rake installed as well. So the extra dependency is not a concern to me.
  3. Since I use Rake all the time, the syntax is at my fingertips. I don’t use Find often enough to use it without checking RI.
  4. The Find version of the script is several times longer than the Rake version (included below for comparison).

However …

The find version has one advantage over the Rake version in that it does not need to pull in the entire list of files into memory at once. That may be important to you.

Comparisons

Here’s the original version again:

  require 'rake'
  FileList["**/*.rb"].egrep(Regexp.new(ARGV.first))

And here is the Find version:

  require 'find'
  RE = Regexp.new(ARGV[0])
  Find.find('.') do |fn|
    next if fn =~ /(^(\.svn|CVS)$)/
    next unless fn =~ /\.rb$/
    open(fn) do |file|
      lines = 0
      file.each do |line|
        lines += 1
        puts "#{fn}:#{lines}:#{line}" if line =~ RE
      end
    end
  end

Update (31/Aug/06)

James Edward Grey II points out that my find example could use a little makeover. First, the regex that causes .svn directories to be skipped is incorrect, it only skips the actual directory, not the contents of the directory. Removing the ”$” from the match will fix that, but he provides a better solution. Replace that entire line with:

    Find.prune if fn =~ /(^(\.svn|CVS)$)/ 

I totally forgot about prune.

A minor correction is the use of the lines counter. He suggests either using each_with_index (I should have thought of that), or better yet, use file.lineno.

Thanks James!


blog comments powered by Disqus

 

Formatted: 06-Jan-09 20:36
Feedback: jim@weirichhouse.org