【问题标题】:Traversing directories and reading from files in ruby on rails在 ruby​​ on rails 中遍历目录和读取文件
【发布时间】:2011-05-29 05:18:18
【问题描述】:

我在弄清楚如何 1) 遍历目录和 2) 获取每个文件 (.txt) 并将其保存为字符串时遇到了一些麻烦。我显然对 ruby​​ 和 rails 都很陌生。

我知道我可以用f=File.open("/path/*.txt") 保存文件,然后用puts f.read 输出它,但我宁愿将它保存为字符串,而不是.txt,并且不知道如何为每个文件执行此操作。

谢谢!

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3


    【解决方案1】:

    您可以使用 Dir.glob 并映射文件名,以使用 IO.read 将每个文件名读入字符串。这是一些伪代码:

    file_names_with_contents = Dir.glob('/path/*.txt').inject({}){|results, file_name| result[file_name] = IO.read(file_name)}
    

    【讨论】:

    • 我不太明白这个。这会返回什么/这是如何工作的?到目前为止我有(抱歉,我不确定如何在新行上获得它):Find.find('/path/') do |f| file=File.open(f) text="" file.each {|line| text << line } Essay.create!(:body => text) end
    【解决方案2】:

    你也可以在这里使用水龙头:

    file_names_with_contents = {}.tap do |h|
      Dir.glob('/path/*.txt').each{|file_name| h[file_name] = IO.read(file_name)}
    end
    

    【讨论】:

      【解决方案3】:

      以下基于python os.walk 函数,它返回一个元组列表: (dirname, dirs, files )。由于这是 ruby​​,因此您会得到一个数组列表: [目录名,目录,文件]。这应该比尝试自己递归遍历目录更容易处理。要运行代码,您需要提供一个 demo_folder。

      def walk(dir)
        dir_list = []
        def _walk(dir, dir_list)
          fns = Dir.entries(dir)
          dirs = []
          files = []
          dirname = File.expand_path(dir)
          list_item = [dirname, dirs, files]
          fns.each do |fn|
            next if [".",".."].include? fn
            path_fn = File.join(dirname, fn)
            if File.directory? path_fn
              dirs << fn
              _walk(path_fn, dir_list)
            else
              files << fn
            end
          end
          dir_list << list_item
        end
      
        _walk(dir, dir_list)
        dir_list
      end
      
      if __FILE__ == $0
      
        require 'json'
      
        dir_list = walk('demo_folder')
        puts JSON.pretty_generate(dir_list)
      end
      

      【讨论】:

        【解决方案4】:

        Jake 的回答已经足够好了,但 each_with_object 会稍微短一些。我也让它递归。

        def read_dir dir
          Dir.glob("#{dir}/*").each_with_object({}) do |f, h|
            if File.file?(f)
              h[f] = open(f).read
            elsif File.directory?(f)
              h[f] = read_dir(f)
            end
          end
        end
        

        当目录是这样的:

        --+ directory_a
          +----file_b
          +-+--directory_c
          | +-----file_d
          +----file_e
        

        然后

        read_dir(directory_a)
        

        将返回:

        {file_b => contents_of_file_b,
         directory_c => {file_d => contents_of_file_d},
         file_e => contents_of_file_e}
        

        【讨论】:

        • 如果您使用 ** 执行 Dir.glob,它不会为您提供所有子目录中的所有文件吗?我原来的解决方案中有这个,但他要求 /path/*.txt 所以我只使用了那个模式。
        猜你喜欢
        • 2011-09-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多