Ofir Kariv
Ofir Kariv

Reputation: 84

How can I find a substring in multiple files?

I need to use Ruby to go over directory and look for text in specific type files.

For example, I have folder with these files: a.txt, b.txt, c.trr, d.trr and I want my code to check only c.trr and d.trr files and find if one of them contains the string "aaa".

I tried some options but non of them seems to work for me.

I tried:

Dir.foreach("/myusername/Desktop/a") do |fname|
    if  (File.extname(fname) == ".trr")
       begin
        fname.each_line do |line|
       if 
        line.scan(Regexp.new('aaa'))
        puts "found it!"
       else
        puts "no can do sir"
        end
        end
        rescue Exception => ex
                puts ex
        end
    end
end

Didn't work. and when I tried to print line variable I got as a response the name of the file and not the lines in it.

I tried to change the scan function to match, and I also tried to change Regexp.new('aaa') to \aaa\.

Non of them seems to work. Does Dir.foreach also opens the file? If it is not, how can I open it? I tried to use File.open(fname) but I got the following exception:

No such file or directory @ rb_sysopen

Upvotes: 1

Views: 217

Answers (2)

Keith Bennett
Keith Bennett

Reputation: 4970

The above answer is excellent, but you can go even a step further in using Ruby's Enumerable processing by creating arrays of those containing and not matching the regex:

with_aaa, without_aaa = Dir["*.trr"].partition do |filename|
  File.read(filename) =~ /aaa/
end

...or, if you don't care about the ones not matching the regex, you can use select instead of partition:

with_aaa = Dir["*.trr"].select do |filename|
  File.read(filename) =~ /aaa/
end

Upvotes: 0

Jonathan Duarte
Jonathan Duarte

Reputation: 778

Usually the Dir methods will return to you just the filename. You'll still need to open and read the file manually.

Dir["*.trr"].each do |fname|
  content = File.read(fname)
  if content =~ /aaa/
    puts "found it in: #{fname}"
  else
    puts "not found in: #{fname}"
  end
end

You could use Dir#[] and pass the matching string, instead of using foreach. Then it's just a matter of comparing the file content against whatever you want.

Upvotes: 1

Related Questions