Forum: Ruby Looking for a way to recursively for a string array through directories and subdirectories

96ae95cf1ca7f6db6a40869b8b3c93de?d=identicon&s=25 amanda honey (pandaporkchop)
on 2013-09-13 18:30
I can get this to work but only in the directory that the script resides
in.
If i change the dir_path to a different directory it says that the file
its trying to read is a directory.
Any help would be welcome...


dir_path = '.'
str = /somearray|with|logts|of|strings/

# Searching for string
Dir.chdir(dir_path) do
  Dir.glob("*") do |filename|
    IO.foreach(filename) do |line|
      if line =~ str
        puts "#{filename}: #{line}   "
        puts "--------------------------------------------------"
        logger = Logger.new($stdout)
    end
  end
end
14b5582046b4e7b24ab69b7886a35868?d=identicon&s=25 Joel Pearson (virtuoso)
on 2013-09-13 20:58
Try using Dir['**/*.*']
Aa082c8b00a50928e5860dcd70bf2368?d=identicon&s=25 tamouse m. (tamouse_m)
on 2013-09-14 04:59
(Received via mailing list)
On Sep 13, 2013, at 11:30 AM, amanda honey <lists@ruby-forum.com> wrote:

> # Searching for string
>
> --
> Posted via http://www.ruby-forum.com/.


The way you've called Dir.glob, it can easily return directories as well
as plain files. Joel's response is a good one, but it can still return
terminal directories that are empty.

Even doing Dir['**/*'] will get you more than you bargained for.

Example: set up a quick demo:

tamara@pontiki:~:2013-09-13@07:07:42
$ cd /tmp

tamara@pontiki:/tmp:2013-09-13@09:37:29
$ mkdir -p test/recursive/dirs.ext

tamara@pontiki:/tmp:2013-09-13@09:37:50
$ ls -al test
total 0
drwxr-xr-x   3 tamara  wheel   102B Sep 13 21:37 ./
drwxrwxrwt  17 root    wheel   578B Sep 13 21:37 ../
drwxr-xr-x   3 tamara  wheel   102B Sep 13 21:37 recursive/

tamara@pontiki:/tmp:2013-09-13@09:38:02
$ ls -alR test
total 0
drwxr-xr-x   3 tamara  wheel   102B Sep 13 21:37 ./
drwxrwxrwt  17 root    wheel   578B Sep 13 21:37 ../
drwxr-xr-x   3 tamara  wheel   102B Sep 13 21:37 recursive/

test/recursive:
total 0
drwxr-xr-x  3 tamara  wheel   102B Sep 13 21:37 ./
drwxr-xr-x  3 tamara  wheel   102B Sep 13 21:37 ../
drwxr-xr-x  2 tamara  wheel    68B Sep 13 21:37 dirs.ext/

test/recursive/dirs.ext:
total 0
drwxr-xr-x  2 tamara  wheel    68B Sep 13 21:37 ./
drwxr-xr-x  3 tamara  wheel   102B Sep 13 21:37 ../

tamara@pontiki:/tmp:2013-09-13@09:38:13
$ touch test/recursive/file

tamara@pontiki:/tmp:2013-09-13@09:39:34
$ touch test/recursive/file_with.ext



Then:

[104] pry(main)> Dir['/tmp/test/**/*'].inject({}){|m,o|
m[o]=File.ftype(o);m}
=> {"/tmp/test/recursive"=>"directory",
 "/tmp/test/recursive/dirs.ext"=>"directory",
 "/tmp/test/recursive/file"=>"file",
 "/tmp/test/recursive/file_with.ext"=>"file"}
[105] pry(main)> Dir['/tmp/test/**/*.*'].inject({}){|m,o|
m[o]=File.ftype(o);m}
=> {"/tmp/test/recursive/dirs.ext"=>"directory",
 "/tmp/test/recursive/file_with.ext"=>"file"}
[106] pry(main)>

So in your code, it will fail if you try IO.foreach on a directory

A simple enough rewrite:

def grep_r(search_criteria, starting_directory='.')
  raise "Search criteria must be a regular expression" unless
search_criteria.kind_of? Regexp
  raise "Starting point not a directory" unless File.directory?
starting_directory
  Dir[FIle.join(starting_directory,"**","*")].each do |entry|
    next unless FIle.ftype(entry) == "file"
    IO.foreach(entry) do |line|
      if line =~ str
        puts "#{filename}: #{line}   "
        puts "--------------------------------------------------"
        # logger = Logger.new($stdout) # ← this is useless, you're not
doing anything with this, and setting it each time through the loop is a
waste
      end # if
    end # IO.foreach
  end # Dir..each
end

grep_r(%r{some|set|of|words|to|find}, '.')
grep_r(%r{someother|set|of|words to
find},File.join(ENV['HOME'],'Documents',"ThatImportantProject"))
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (robert_k78)
on 2013-09-14 12:26
(Received via mailing list)
On Sat, Sep 14, 2013 at 4:58 AM, Tamara Temple <tamouse.lists@gmail.com>
wrote:

>         puts "--------------------------------------------------"
>         # logger = Logger.new($stdout) # ← this is useless, you're not doing
anything with this, and setting it each time through the loop is a waste
>       end # if
>     end # IO.foreach
>   end # Dir..each
> end
>
> grep_r(%r{some|set|of|words|to|find}, '.')
> grep_r(%r{someother|set|of|words to
find},File.join(ENV['HOME'],'Documents',"ThatImportantProject"))

Why did nobody recommend Find or Pathname?

require 'find'

rx = /somearray|with|logts|of|strings/

Find.find '.' do |f|
  next if File.directory? f

  File.foreach f do |line|
    if rx =~ line
      puts f
      break
    end
  end
end

# or

Find.find '.' do |f|
  next if File.directory? f

  File.foreach(f).find {|line| rx =~ line} and puts f
end

# or

require 'pathname'

Pathname.pwd.find do |f|
  next if f.directory?

  f.each_line
    if rx =~ line
      puts f
      break
    end
  end
end

# or

Pathname.pwd.find do |f|
  next if f.directory?

  f.each_line.find {|line| rx =~ line} and puts f
end


If file names are only to be displayed and not further processed in
the Ruby program there is a much simpler solution on the command
prompt of a reasonable OS:

find -type f -exec egrep -l 'somearray|with|logts|of|strings' {} +

Cheers

robert
Aa082c8b00a50928e5860dcd70bf2368?d=identicon&s=25 tamouse m. (tamouse_m)
on 2013-09-15 00:50
(Received via mailing list)
On Sep 14, 2013, at 5:25 AM, Robert Klemme <shortcutter@googlemail.com>
wrote:

>>      if line =~ str
>
> Why did nobody recommend Find or Pathname?

WHY OH WHY????

cos

>
> require 'find'
>
> rx = /somearray|with|logts|of|strings/
>
> Find.find '.' do |f|
>  next if File.directory? f

This will pass things other than files: pipes, sockets, etc

>
> Pathname.pwd.find do |f|
> # or
> prompt of a reasonable OS:
>
> find -type f -exec egrep -l 'somearray|with|logts|of|strings' {} +

or

grep -rlE 'somearray|with|logts|of|strings' .

TMTOWTDT
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (robert_k78)
on 2013-09-15 13:36
(Received via mailing list)
On Sun, Sep 15, 2013 at 12:49 AM, Tamara Temple
<tamouse.lists@gmail.com> wrote:
>
> On Sep 14, 2013, at 5:25 AM, Robert Klemme <shortcutter@googlemail.com> wrote:

>> Why did nobody recommend Find or Pathname?
>
> WHY OH WHY????

The horrors...

> cos
>
>> require 'find'
>>
>> rx = /somearray|with|logts|of|strings/
>>
>> Find.find '.' do |f|
>>  next if File.directory? f
>
> This will pass things other than files: pipes, sockets, etc

That is easily fixed

Find.find '.' do |f|
  File.foreach(f).find {|line| rx =~ line} and puts f if File.file? f
end

> TMTOWTDT
Right!  I'm so used to using find that I keep forgetting *grep's
option "-r".  Thank you for the reminder!

Cheers

robert
96ae95cf1ca7f6db6a40869b8b3c93de?d=identicon&s=25 amanda honey (pandaporkchop)
on 2013-09-20 02:43
Thanks guys!

Pathname.pwd.find do |f|
  next if f.directory?

  f.each_line.find {|line| strcpyArray =~ line and puts "#{f}: #{line}
" }

end

Worked perfectly for what I needed to do.
I am learning allot from this. It was easy to whip a script in bash to
do this but it really just takes too much resources using grep. This
works so much better. =-) I cant wait till I am not so green with Ruby
=-)
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (robert_k78)
on 2013-09-20 09:55
(Received via mailing list)
On Fri, Sep 20, 2013 at 2:43 AM, amanda honey <lists@ruby-forum.com>
wrote:
> Worked perfectly for what I needed to do.
> I am learning allot from this. It was easy to whip a script in bash to
> do this but it really just takes too much resources using grep. This
> works so much better. =-) I cant wait till I am not so green with Ruby
> =-)

How did you do it in the shell that it took so much resources?  Did
you try the variant I have posted earlier?

Kind regards

robert
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.