使用Dir.glob获取文件夹中所有的csv和xls文件

13
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
我正在尝试用Ruby编写一个简单的脚本,使我可以从命令行调用它,例如ruby counter.rb mailing_list1,然后它会进入文件夹并统计所有.csv和.xls文件。
我打算在每个文件上操作,获取行数等等。
目前files_to_process数组实际上是一个嵌套数组 - 我不想要那样。我想要一个包含所有.csv和.xls文件的单一数组。
由于我不知道如何从Dir.glob中yield,所以我将它们添加到了一个数组中并返回了该数组。
如何使用单个数组来完成这个任务?
3个回答

52

只需将文件扩展名放在一起组成一个组:

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

3
在我看来,这是更符合 Ruby 风格的回答。它只有一行代码且易于阅读。不过,我可能会这样写:Dir["#{path}/**/*.{csv,xls}]两种方法其实差别不大。 - Merovex

14

好的,yield很简单。只需使用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 关键字将数据发送到该块中。如果该块可能存在也可能不存在,则通常使用 block_given? 来与 yield 一起使用。

yield f if block_given?

更新

通过直接将您的块传递给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

虽然这个块/过程的转换是一个稍微高级的话题。


@Merovex:请注意,这篇文章回答了我认为是直接问题(“我怎么才能从这个中止并返回值?”),而不是完整解决方案的礼物包装。 - Sergio Tulentsev
说得好,不过请求中的“yield”部分被深深地埋在叙述中。在基础问题中提到这一点可能会有所帮助。;-) - Merovex

2
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 文件的数组。构建文件名数组可能不是你真正想要的,特别是当有很多文件时。在这种情况下,如果你不需要先知道文件数量,使用 Dir.glob 返回的 Enumerator 方法会更合适。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接