From: Phrogz Date: 2007-10-02T22:50:06+09:00 Subject: Re: finding files with regular expressions On Oct 2, 6:17 am, Remco Hh wrote: > I want to search in a directory for files, matching a certain regular > expression. The script should not return true or false, but should give > me a list (array) of filenames which are found. Here's my 'findfile' script that I use daily. It lets you use a regexp for the filename, file content, specify depth of search, whether or not to show all matches inside a file, and so on. (You may need to unwrap some of the longer lines after copy/paste.) See additional notes at the end. Slim2:/usr/local/bin phrogz$ cat findfile #!/usr/bin/env ruby USAGE = < max_depth begin if File.directory?( path ) yield( path, depth ) if include_directories files = Dir.entries( path ).select{ |f| true unless f=~/^\. {1,2}$/ } unless files.empty? files.collect!{ |file_path| Dir.crawl( path+'/'+file_path, max_depth, include_directories, depth+1, &block ) }.flatten! end return files else yield( path, depth ) end rescue SystemCallError => the_error warn "ERROR: #{the_error}" end end end start_time = Time.new name_match = Regexp.new(ARGS[:name_regexp], true ) content_match = ARGS[:content_regexp] && Regexp.new( ". {0,20}#{ARGS[:content_regexp]}.{0,20}", !ARGS[:usecase] ) file_count = 0 matching_count = 0 Dir.crawl( '.', ARGS[:max_depth], ARGS[:includedirs] && ! content_match){ |file_path, depth| if File.split( file_path )[ 1 ] =~ name_match if content_match if ARGS[:showall] shown_file = false IO.readlines( file_path ).each_with_index{ | line_text,line_number| if match = line_text[content_match] unless shown_file puts file_path matching_count += 1 shown_file = true end puts ( "%5d: " % line_number ) + match end } puts " " if shown_file elsif IO.read( file_path ) =~ content_match puts file_path," #{$~}"," " matching_count += 1 end else puts file_path matching_count += 1 end end file_count += 1 } elapsed = Time.new - start_time puts "Found #{matching_count} file#{matching_count==1?'':'s'} (out of #{file_count}) in #{elapsed} seconds" You do have to watch for shell escaping of the regexp, either escaping chars as needed or quoting your regexp: Slim2:/usr/local/bin phrogz$ findfile \d ./findfile ./index_gem_repository.rb ./p4d ./rdoc ./rdoc-osa ./svnadmin ./svndumpfilter ./update_rubygems Found 8 files (out of 40) in 0.001228 seconds Slim2:/usr/local/bin phrogz$ findfile \\d ./p4 ./p4d ./rot13 ./sqlite3 Found 4 files (out of 40) in 0.001088 seconds Slim2:/usr/local/bin phrogz$ findfile \\d$ ./p4 ./rot13 ./sqlite3 Found 3 files (out of 40) in 0.001118 seconds Slim2:/usr/local/bin phrogz$ findfile "\d$" ./p4 ./rot13 ./sqlite3 Found 3 files (out of 40) in 0.001298 seconds