While hacking code and introducing bugs to a project, I sometimes find it necessary to search for a string in every file in a directory. For example, suppose I'm pulling my hair out trying to find where in a drupal project a certain function is called. It could be in a module, or a theme, or the template file. Egads! the code is all over the place and I most certainly do not want to open every damn file and search for the function.
I had been using a script called 'find_in_dir' to help me find a string in a directory and the script is as follows:
The usage of the script was simple:
[jezra@fatlappy ~]$ find_in_dir PATH_TO_SEARCH STRING_TO_FIND
The script would recursively search each file in the directory and output the lines in a file containing the search string and then output the path to the file that was searched. While this definitely did what I needed, I found that I was spending too much time tracking down the path to the file because all of the output was just plain text on the screen.
What I really wanted/needed was something to differentiate the file path in the output from the rest of the output, so I fired up geany and hacked together some Ruby code to do what I need (and output the file path using green text. ohhhhh fancy!)
Enter the Ruby
#make a helpy helper function
def help()
print "--USAGE--\n"
print "findindir directory string_to_find\n"
end
#find (
#loc: path to a file or directory,
#string: the string to search for
#)
def find(loc, string)
#is the location a directory?
if File.directory?(loc)
#loop through each item in the directory
Dir.foreach(loc) do |name|
#ignore . and ..
if name!='.' and name!='..'
#what is the path of the item?
path = File.join(loc,name)
#recurse
find(path, string)
end
end
else #this is a file
#by default, we state that there is no match to the string
match = false
#loop through each line in the file
File.foreach(loc) do |line|
#does the line contain our string?
if line.include?(string)
match = true
puts line
end
end
#a match was found
if match
puts "\e[32m#{loc}\e[0m\n\n"
end
end
end
#set some vars based on user input
start_loc = ARGV[0]
string = ARGV[1]
#did the user enter enough data?
if start_loc.nil? or string.nil?
help
else
#determine the absolute path to the start location
path = File.absolute_path(start_loc)
#find that shit!
find(path, string)
end
Having trouble copying the code? get it at http://hoof.jezra.net/snip/6
The code isn't perfect and could certainly use some improvements, such as:
- ignore broken symlinks
- output the line number where matches were found
- default to current working directory when the user doesn't specify a directory
It may not be the best, but it's a start. Now quit reading and go find something.
find $1 -type f -exec grep -i $2 {} \; -printf "[%p]\n" | colorit
It has the side effect that it might also colorize other parts of the results, and I didn't quickly see a way to safely remove the brackets after colorization.
grep -ir --color=always pattern directory
the -r recurses through all subdirectories, and --color=always colorises the output.