Dir.glob для получения всех файлов csv и xls в папке

folder_to_analyze = ARGV.first
folder_path = File.join(Dir.pwd, folder_to_analyze)

unless File.directory?(folder_path)
  puts "Error: #{folder_path} no es un folder valido."
  exit
end

def get_csv_file_paths(path)
  files = []
  Dir.glob(path + '/**/*.csv').each do |f|
    files << f
  end
  return files
end

def get_xlsx_file_path(path)
  files = []
  Dir.glob(path + '/**/*.xls').each do |f|
    files << f
  end
  return files
end

files_to_process = []
files_to_process << get_csv_file_paths(folder_path)
files_to_process << get_xlsx_file_path(folder_path)
puts files_to_process[1].length # Not what I want, I want:
# puts files_to_process.length

Я пытаюсь сделать простой script в Ruby, который позволяет мне вызывать его из командной строки, например ruby counter.rb mailing_list1, и он переходит в папку и учитывает все файлы .csv и .xls.

Я намерен работать с каждым файлом, получая количество строк и т.д.

В настоящее время массив files_to_process на самом деле является массивом массива - я этого не хочу. Я хочу иметь один массив из файлов .csv и .xls.

Так как я не знаю, как уступить из вызова Dir.glob, я добавил их в массив и вернул это.

Как это сделать, используя один массив?

Ответ 1

Ну, урожайность проста. Просто yield.

def get_csv_file_paths(path)
  Dir.glob(path + '/**/*.csv').each do |f|
    yield f
  end
end

def get_xlsx_file_path(path)
  Dir.glob(path + '/**/*.xls').each do |f|
    yield f
  end
end

files_to_process = []
get_csv_file_paths(folder_path) {|f| files_to_process << f }
get_xlsx_file_path(folder_path) {|f| files_to_process << f }

puts files_to_process.length

Каждый метод в ruby ​​может быть передан блоком. И ключевое слово yield отправляет данные в этот блок. Если блок может быть или не может быть предоставлен, yield обычно используется с block_given?.

yield f if block_given?

Update

Код можно упростить, передав свой блок непосредственно на glob.each:

def get_csv_file_paths(path, &block)
  Dir.glob(path + '/**/*.txt').each(&block)
end

def get_xlsx_file_path(path, &block)
  Dir.glob(path + '/**/*.xls').each(&block)
end

Несмотря на то, что это преобразование блока /proc - это немного продвинутая тема.

Ответ 2

Просто вставьте расширения файлов вместе в одну группу:

Dir[path + "/**/*.{csv,xls}"]

Ответ 3

def get_folder_paths(root_path)
  Dir.glob('**/*.csv') + Dir.glob('**/*.xls')
end

folder_path = File.join(Dir.pwd, ARGV.first || '')
raise "#{folder_path} is not a valid folder" unless File.directory?(folder_path)

puts get_folder_paths(folder_path).length

Метод get_folder_paths возвращает массив файлов CSV и XLS. Создание массива имен файлов может быть не тем, что вы действительно хотите, особенно если их много. Подход, использующий Enumerator, возвращаемый Dir.glob, был бы более уместным в этом случае, если вам сначала не понадобилось количество файлов.