Back to blog index 2018-11-27

Not invented here, dude

I can never remember the syntax for find. And when I do remember it, it tends to be something stupid like find . -name package.json. Thing is, I used to have this exact problem with grep where I would tell it to grep -i -r 'foo' * and then my wrists would look at me sorrowfully like “what did we ever do to you, why are you giving us RSI” and I’d hate myself.

Then along came ack and all was well, because let’s face it: 99% of the time you want to search the directory you’re in for files containing a case-insensitive string. Right? So ack foo. Monkey simple. Having identified my problem with find, obviously the sensible thing to do is to add an alias to my terminal. Try this on for size: alias hitta="find . -name". Added to dotfiles, case closed.

But I’m never one for sensible things. WITNESS ME -

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def search_in_directory(haystack, needles)
  Dir.entries(haystack).each do |item|
    next if item == "."
    next if item == ".."

    fullpath = "#{haystack}/#{item}"

    if File.file?(fullpath)
      puts fullpath if needles.any? { |needle| item.includes?(needle) }
    elsif File.directory?(fullpath)
      search_in_directory(fullpath, needles)
    end
  end
end

search_in_directory(".", ARGV)

That’s right, foolish mortal: I just rewrote the good parts of find in Crystal. No, fuck you, YOU apologize!

Performance benchmarks, run on the (admittedly small-ish) Projects folder on my home machine:

1
2
3
4
$ time find . -name package.json
real    0m1.722s
user    0m0.258s
sys 0m1.459s
1
2
3
4
$ time hitta package.json
real    0m1.891s
user    0m0.390s
sys 0m1.586s

Yes, it’s a little slower than the Gnu implementation but then they’ve had, what, 25 years to optimize it? To be honest I haven’t looked at their implementation but I bet my code is more readable. So anyway that little program is now in my bin folder and that concludes today’s episode of “Poor Life Choices: why I really shouldn’t be writing code for a living”