Rubyを使ってフォルダからすべてのファイル名を取得したい。
ショートカットオプションもあります。
Dir["/path/to/search/*"]
また、任意のフォルダまたはサブフォルダにあるすべてのRubyファイルを見つけたい場合は、
Dir["/path/to/search/**/*.rb"]
Dir.entries(folder)
例:
Dir.entries(".")
出典: http://Ruby-doc.org/core/classes/Dir.html#method- c-entries
次のスニペットは、サブディレクトリと"."
、".."
のドット付きフォルダをスキップして、ディレクトリ内のファイルの名前を正確に示しています。
Dir.entries("your/folder").select {|f| !File.directory? f}
すべてのファイル(厳密にはファイルのみ)を再帰的に取得するには
Dir.glob('path/**/*').select{ |e| File.file? e }
あるいはディレクトリではないもの(File.file?
は非正規ファイルを拒否します):
Dir.glob('path/**/*').reject{ |e| File.directory? e }
Find#find
のようなパターンベースの検索方法で Dir.glob
を使う方が実際には良いです。 この答えは「Rubyでディレクトリを再帰的に一覧表示するためのワンライナー?」への回答 を参照してください。
これは私のために働く:
隠しファイルが欲しくないなら[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について知りません
個人的に、私はこれがフォルダ内のファイルをループするために最も有用であることを見込んでいます。
Dir['/etc/path/*'].each do |file_name|
next if File.directory? file_name
end
これは、ディレクトリ内のファイルを見つけるための解決策です。
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
Ruby 2.5ではDir.children
を使うことができます。 "。"以外のファイル名を配列として取得します。そして「..」
例:
Dir.children("testdir") #=> ["config.h", "main.rb"]
ディレクトリ内のすべてのファイル名を取得しながら、このスニペットを使用して、ディレクトリ[.
、..
]と.
で始まる隠しファイルの両方を拒否することができます。
files = Dir.entries("your/folder").reject {|f| File.directory?(f) || f[0].include?('.')}
これは私のために働くものです:
Dir.entries(dir).select { |f| File.file?(File.join(dir, f)) }
Dir.entries
は文字列の配列を返します。次に、dir
が現在の作業ディレクトリと同じでない限り、ファイルのフルパスをFile.file?
に提供する必要があります。だからこそ、これはFile.join()
です。
このスレッドでの提案に加えて、ドットファイル(.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を使用していました。
Rake::FileList
を使うこともできます(rake
の依存関係がある場合)。
FileList.new('lib/*') do |file|
p file
end
APIによると:
FileListsは怠惰です。ファイルリストに含める可能性のあるファイルのグロブパターンのリストが与えられたとき、ファイルを見つけるためにファイル構造を検索する代わりに、FileListは後者の使用のためのパターンを保持します。
Dir.new('/home/user/foldername').each { |file| puts file }
ファイル名の配列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')
を使用してください。
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
ディレクトリとすべてのサブディレクトリからファイルの相対パスを返します。
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