web-dev-qa-db-ja.com

Rubyを使ってフォルダからすべてのファイルの名前を取得する

Rubyを使ってフォルダからすべてのファイル名を取得したい。

314
Željko Filipin

ショートカットオプションもあります。

Dir["/path/to/search/*"]

また、任意のフォルダまたはサブフォルダにあるすべてのRubyファイルを見つけたい場合は、

Dir["/path/to/search/**/*.rb"]
474
Ian Eccles
Dir.entries(folder)

例:

Dir.entries(".")

出典: http://Ruby-doc.org/core/classes/Dir.html#method- c-entries

154
Željko Filipin

次のスニペットは、サブディレクトリと"."".."のドット付きフォルダをスキップして、ディレクトリ内のファイルの名前を正確に示しています。

Dir.entries("your/folder").select {|f| !File.directory? f}
86
Emiliano Poggi

すべてのファイル(厳密にはファイルのみ)を再帰的に取得するには

Dir.glob('path/**/*').select{ |e| File.file? e }

あるいはディレクトリではないもの(File.file?は非正規ファイルを拒否します):

Dir.glob('path/**/*').reject{ |e| File.directory? e }

代替ソリューション

Find#findのようなパターンベースの検索方法で Dir.glob を使う方が実際には良いです。 この答えは「Rubyでディレクトリを再帰的に一覧表示するためのワンライナー?」への回答 を参照してください。

31
konsolebox

これは私のために働く:

隠しファイルが欲しくないなら[1]、Dir []を使ってください。

# With a relative path, Dir[] will return relative paths 
# as `[ './myfile', ... ]`
#
Dir[ './*' ].select{ |f| File.file? f } 

# Want just the filename?
# as: [ 'myfile', ... ]
#
Dir[ '../*' ].select{ |f| File.file? f }.map{ |f| File.basename f }

# Turn them into absolute paths?
# [ '/path/to/myfile', ... ]
#
Dir[ '../*' ].select{ |f| File.file? f }.map{ |f| File.absolute_path f }

# With an absolute path, Dir[] will return absolute paths:
# as: [ '/home/../home/test/myfile', ... ]
#
Dir[ '/home/../home/test/*' ].select{ |f| File.file? f }

# Need the paths to be canonical?
# as: [ '/home/test/myfile', ... ]
#
Dir[ '/home/../home/test/*' ].select{ |f| File.file? f }.map{ |f| File.expand_path f }

さて、Dir.entriesは隠しファイルを返すので、ワイルドカードのアスタリスクは必要ありません(ディレクトリ名と一緒に変数を渡すことができます)が、ベース名が直接返されるので、Fileは.xxx関数は機能しません。

# In the current working dir:
#
Dir.entries( '.' ).select{ |f| File.file? f }

# In another directory, relative or otherwise, you need to transform the path 
# so it is either absolute, or relative to the current working dir to call File.xxx functions:
#
home = "/home/test"
Dir.entries( home ).select{ |f| File.file? File.join( home, f ) }

[1] unixの.dotfile、私はWindowsについて知りません

12
user1115652

個人的に、私はこれがフォルダ内のファイルをループするために最も有用であることを見込んでいます。

Dir['/etc/path/*'].each do |file_name|
  next if File.directory? file_name 
end
8
mr.buttons

これは、ディレクトリ内のファイルを見つけるための解決策です。

files = Dir["/work/myfolder/**/*.txt"]

files.each do |file_name|
  if !File.directory? file_name
    puts file_name
    File.open(file_name) do |file|
      file.each_line do |line|
        if line =~ /banco1/
          puts "Found: #{line}"
        end
      end
    end
  end
end
8
gilcierweb

Ruby 2.5ではDir.childrenを使うことができます。 "。"以外のファイル名を配列として取得します。そして「..」

例:

Dir.children("testdir")   #=> ["config.h", "main.rb"]

http://Ruby-doc.org/core-2.5.0/Dir.html#method-c-children

5
Mario Pérez

ディレクトリ内のすべてのファイル名を取得しながら、このスニペットを使用して、ディレクトリ[...]と.で始まる隠しファイルの両方を拒否することができます。

files = Dir.entries("your/folder").reject {|f| File.directory?(f) || f[0].include?('.')}
4
Lahiru

これは私のために働くものです:

Dir.entries(dir).select { |f| File.file?(File.join(dir, f)) }

Dir.entriesは文字列の配列を返します。次に、dirが現在の作業ディレクトリと同じでない限り、ファイルのフルパスをFile.file?に提供する必要があります。だからこそ、これはFile.join()です。

3
yegor256

このスレッドでの提案に加えて、ドットファイル(.gitignoreなど)も返す必要がある場合は、Dir.globを使用してフラグを含める必要があることに言及したいと思います。Dir.glob("/path/to/dir/*", File::FNM_DOTMATCH)デフォルトでは、Dirです。エントリには、ドットファイルと現在の親ディレクトリが含まれます。

興味のある人のために、私はここでの答えが実行時間において互いにどのように比較されたかに興味がありました、ここに深く入れ子になった階層に対する結果がありました。最初の3つの結果は非再帰的です。

       user     system      total        real
Dir[*]: (34900 files stepped over 100 iterations)
  0.110729   0.139060   0.249789 (  0.249961)
Dir.glob(*): (34900 files stepped over 100 iterations)
  0.112104   0.142498   0.254602 (  0.254902)
Dir.entries(): (35600 files stepped over 100 iterations)
  0.142441   0.149306   0.291747 (  0.291998)
Dir[**/*]: (2211600 files stepped over 100 iterations)
  9.399860  15.802976  25.202836 ( 25.250166)
Dir.glob(**/*): (2211600 files stepped over 100 iterations)
  9.335318  15.657782  24.993100 ( 25.006243)
Dir.entries() recursive walk: (2705500 files stepped over 100 iterations)
 14.653018  18.602017  33.255035 ( 33.268056)
Dir.glob(**/*, File::FNM_DOTMATCH): (2705500 files stepped over 100 iterations)
 12.178823  19.577409  31.756232 ( 31.767093)

これらは次のベンチマークスクリプトで生成されました。

require 'benchmark'
base_dir = "/path/to/dir/"
n = 100
Benchmark.bm do |x|
  x.report("Dir[*]:") do
    i = 0
    n.times do
      i = i + Dir["#{base_dir}*"].select {|f| !File.directory? f}.length
    end
    puts " (#{i} files stepped over #{n} iterations)"
  end
  x.report("Dir.glob(*):") do
    i = 0
    n.times do
      i = i + Dir.glob("#{base_dir}/*").select {|f| !File.directory? f}.length
    end
    puts " (#{i} files stepped over #{n} iterations)"
  end
  x.report("Dir.entries():") do
    i = 0
    n.times do
      i = i + Dir.entries(base_dir).select {|f| !File.directory? File.join(base_dir, f)}.length
    end
    puts " (#{i} files stepped over #{n} iterations)"
  end
  x.report("Dir[**/*]:") do
    i = 0
    n.times do
      i = i + Dir["#{base_dir}**/*"].select {|f| !File.directory? f}.length
    end
    puts " (#{i} files stepped over #{n} iterations)"
  end
  x.report("Dir.glob(**/*):") do
    i = 0
    n.times do
      i = i + Dir.glob("#{base_dir}**/*").select {|f| !File.directory? f}.length
    end
    puts " (#{i} files stepped over #{n} iterations)"
  end
  x.report("Dir.entries() recursive walk:") do
    i = 0
    n.times do
      def walk_dir(dir, result)
        Dir.entries(dir).each do |file|
          next if file == ".." || file == "."

          path = File.join(dir, file)
          if Dir.exist?(path)
            walk_dir(path, result)
          else
            result << file
          end
        end
      end
      result = Array.new
      walk_dir(base_dir, result)
      i = i + result.length
    end
    puts " (#{i} files stepped over #{n} iterations)"
  end
  x.report("Dir.glob(**/*, File::FNM_DOTMATCH):") do
    i = 0
    n.times do
      i = i + Dir.glob("#{base_dir}**/*", File::FNM_DOTMATCH).select {|f| !File.directory? f}.length
    end
    puts " (#{i} files stepped over #{n} iterations)"
  end
end

ファイル数の違いは、デフォルトで隠しファイルを含むDir.entriesによるものです。 Dir.entriesは、ファイルがディレクトリかどうかを判断するためにファイルの絶対パスを再構築する必要があるため、この場合もう少し時間がかかりましたが、それでも再帰的な場合の他のオプションよりずっと長くかかりました。これはすべてOSX上のRuby 2.5.1を使用していました。

1
Ben

Rake::FileListを使うこともできます(rakeの依存関係がある場合)。

FileList.new('lib/*') do |file|
  p file
end

APIによると:

FileListsは怠惰です。ファイルリストに含める可能性のあるファイルのグロブパターンのリストが与えられたとき、ファイルを見つけるためにファイル構造を検索する代わりに、FileListは後者の使用のためのパターンを保持します。

https://docs.Ruby-lang.org/en/2.1.0/Rake/FileList.html

1
Artur Beljajev
Dir.new('/home/user/foldername').each { |file| puts file }
1
Ashwin

ファイル名の配列symlinkを含むを取得したい場合は、

Dir.new('/path/to/dir').entries.reject { |f| File.directory? f }

あるいは

Dir.new('/path/to/dir').reject { |f| File.directory? f }

もしあなたが行きたいのならシンボリックリンクなしで

Dir.new('/path/to/dir').select { |f| File.file? f }

他の回答に示されているように、すべてのファイルを再帰的に取得したい場合はDir.glob('/path/to/dir/**/*')の代わりにDir.new('/path/to/dir')を使用してください。

1
Mikhail Vasin
def get_path_content(dir)
  queue = Queue.new
  result = []
  queue << dir
  until queue.empty?
    current = queue.pop
    Dir.entries(current).each { |file|
      full_name = File.join(current, file)
      if not (File.directory? full_name)
        result << full_name
      elsif file != '.' and file != '..'
          queue << full_name
      end
    }
  end
  result
end

ディレクトリとすべてのサブディレクトリからファイルの相対パスを返します。

0
punksta

IRBのコンテキストでは、現在のディレクトリにあるファイルを取得するために次のコマンドを使用できます。

file_names = `ls`.split("\n")

他のディレクトリでもこれを機能させることができます。

file_names = `ls ~/Documents`.split("\n")

このコードは、拡張子を持つファイル名のみを返します(グローバルパスなし)

Dir.children("/path/to/search/")

1つの簡単な方法は次のとおりです。

dir = './' # desired directory
files = Dir.glob(File.join(dir, '**', '*')).select{|file| File.file?(file)}

files.each do |f|
    puts f
end
0