user3472065
user3472065

Reputation: 1389

Recursively scan specific folders for a file in ruby

I'm trying to recursively scan specific folders and search a specific file.

In the root folder (e.g., C:\Users\Me), I would like to scan just the folders called my* (so, the folders that start with the letters 'my' + whatever), then see if there is files .txt and store the first line in a variable.

For the scan i'm trying this code, but without succeed

require 'find'

pdf_file_paths = []
path_to_search = ['C:\Users\Me'];

Find.find('path_to_search') do |path|
    if path =~ /.*\.txt$/
        #OPEN FILE
end

Upvotes: 1

Views: 411

Answers (3)

Arup Rakshit
Arup Rakshit

Reputation: 118261

I'd do as below :

first_lines_of_each_file = []
Dir.glob("C:/Users/Me/**/my**/*.txt",File::FNM_CASEFOLD) do |filepath|
  File.open(filepath,'rb') { |file| first_lines_of_each_file << file.gets }
end

File::FNM_CASEFOLD constant would search all the directories and files using case insensitive search. But if you want case sensitive search, then don't need use the second argument File::FNM_CASEFOLD.

If you have directories organized as

C:/Users/Me/
|- my_dir1/
    |- a.txt
    |- my_dir2/
        |- foo.txt
        |- baz.doc
|- my_dir3/
    |- biz.txt
  • Dir.glob("C:/Users/Me/**/my**/*.txt" will give you all the .txt files. As the search is here recursive.

  • Dir.glob("C:/Users/Me/my**/*.txt" will give you only the .txt files, that resides inside the directory, which are direct children of C:/Users/Me/. That's only files you will get are a.txt, biz.txt.

Upvotes: 1

Kashyap
Kashyap

Reputation: 4796

This should do the job:

lines = Dir.glob("#{path}/**/my*/*.txt").map do |filename|
  File.open(filename) do |f|
    f.gets
  end
end

Dir.glob is similar to the glob executable on a *nix machine. This also works on Windows. gets gets the first line. Ensure that you use a forward slash even for a Windows machine.

Upvotes: 1

BroiSatse
BroiSatse

Reputation: 44675

I am not sure whether this is the cleanest solution, but you can try:

def find_files(file_name, root_path, folder_pattern = nil)
  root_path = File.join(root_path, '')
  paths = Dir[File.join(root_path, '**', file_name)]
  paths.keep_if! {|p| p.slice(path.size, p.size).split('/').all? {|s| s =~ folder_pattern}} if folder_pattern
end

find_files('C:/Users/Me', 'find_me.txt', /my.*/)

Upvotes: 0

Related Questions