Rubyでディレクトリを再帰的にリストするワンライナー?


96

Rubyでディレクトリ(ファイルを除く)の配列を取得するための最速で最も最適化された1行の方法は何ですか?

ファイルを含めるのはどうですか?


2
最速で、最も最適化された、ワンライナーは、読み取り可能/保守可能であるとは言えません。そして、ベンチマークと簡単なテストを使用してこれを見つけることができます。
ティンマン

回答:


180
Dir.glob("**/*/") # for directories
Dir.glob("**/*") # for all files

代わりにDir.glob(foo)書き込むこともできますDir[foo](ただしDir.glob、ブロックを取得することもできます。その場合、配列を作成する代わりに各パスが生成されます)。

Ruby Globドキュメント


10
Dir.glob("**/")シンボリックリンクも必要でない限り使用してください
ヨハネス

6
隠しファイルと隠しディレクトリはどうですか?
アレディアフェリア2012

6
一致結果にドットファイルを含めるには、File::FNM_DOTMATCHフラグを使用します。
x-yuri 2014

2
@ x-yuri、ありがとう!:フラグはところで、このように指定されているDir.glob("**/*", File::FNM_DOTMATCH)
VLZ

2
ドキュメントは次のとおり
stephen.hanson

53

私はここでのソリューションのどれも隠しディレクトリ(例えば '.test')を扱っていないと思います:

require 'find'
Find.find('.') { |e| puts e if File.directory?(e) }

Find.find('/tmp').collect {|_|_}役に立ちました
Alexander Bird

検索には注意してください、それはシンボリックリンクをたどりません:stackoverflow.com/questions/3974087/...は
leebutts

31

ディレクトリのリストについては、

Dir['**/']

Unixではディレクトリもファイルであるため、ファイルのリストはより困難です。そのため、タイプをテストするか、他のエントリの親である返されたリストからエントリを削除する必要があります。

Dir['**/*'].reject {|fn| File.directory?(fn) }

そして、すべてのファイルとディレクトリのリストについては

Dir['**/*']

彼は「ファイルのみ」ではなく「ファイルも含む」と言ったので、ディレクトリを削除する必要はありません。
sepp2k

1
@ sepp2kはい、irbで遊んでいたときにこの部分を逃しました。しかし、誰かが似たようなものを検索する可能性がある場合に備えて、これはここに残します:-)
MBO

7

高速ワンライナー

ディレクトリのみ

`find -type d`.split("\n")

ディレクトリと通常のファイル

`find -type d -or -type f`.split("\n")`

純粋で美しいルビー

require "pathname"

def rec_path(path, file= false)
  puts path
  path.children.collect do |child|
    if file and child.file?
      child
    elsif child.directory?
      rec_path(child, file) + [child]
    end
  end.select { |x| x }.flatten(1)
end

# only directories
rec_path(Pathname.new(dir), false)
# directories and normal files
rec_path(Pathname.new(dir), true)

1
False:Dir.glob( "#{DIRECTORY} / ** / * /")。map {| directory | Pathname.new(directory)}
Robert Ross

誰かがそのend.select {}.flatten()部分を説明できますか?全体的に機能が好きです。それは配列の配列を作成するように見えますか?あなたがそれを配列に割り当てて文字列の配列を得ることができるようにelseifrec_path(child, file) << child.to_sありがとう!
MCP 2013年

7

ここの他の回答で述べたように、を使用できますDir.glob。フォルダーには奇妙な文字が多数含まれている場合があり、グロブ引数はパターンであるため、一部の文字には特別な意味があることに注意してください。そのため、次のようなことを行うのは安全ではありません。

Dir.glob("#{folder}/**/*")

代わりに:

Dir.chdir(folder) { Dir.glob("**/*").map {|path| File.expand_path(path) } }

2

PHPやその他の言語では、ディレクトリとそのすべてのサブディレクトリのコンテンツを取得するには、コードを数行記述する必要がありますが、Rubyでは2行かかります。

require 'find'
Find.find('./') do |f| p f end

これにより、現在のディレクトリとそのすべてのサブディレクトリの内容が出力されます。

または短く、以下の’**’表記を使用できます。

p Dir['**/*.*']

同じ結果を得るために、PHPまたはJavaで何行書くでしょうか。


13
ソースを引用せずにmustap.com/rubyzone_post_162_recursive-directory-listingから直接コピーして貼り付けるための反対投票...
eckza

@kivetrosアーカイブのリンクを含めるように回答を編集しました:-)
onebree

0

1行の解決策ではありませんが、これがルビ呼び出しを使用して行う最善の方法だと思います。

最初にすべてのファイルを再帰的に削除します
2番目にすべての空のディレクトリを削除します

Dir.glob("./logs/**/*").each { |file| File.delete(file) if File.file? file }
Dir.glob("./logs/**/*/").each { |directory| Dir.delete(directory) }

3
彼/彼女はファイル/ディレクトリを削除したくありません。
DarekNędza、2015

単一の行で両方のファイルとディレクトリに対してこれを行う方法は?
vipin8169 2016年

0

Railsプロジェクトディレクトリの動的な検出とDir.globを組み合わせる例を次に示します。

dir = Dir.glob(Rails.root.join('app', 'assets', 'stylesheets', '*'))

私はこれを試しましたconfig.assets.paths << Rails.root.join("app", "assets", "*")が、それでもアセットフォルダー内のサブフォルダーとファイルを表示できませんでしたRails.application.config.assets.paths
vipin8169

-1
Dir.open(Dir.pwd).map { |h| (File.file?(h) ? "#{h} - file" : "#{h} - folder") if h[0] != '.' }

ドットはnilを返し、コンパクトを使用


1
これはあまりエレガントではなく、そうするためにはさらに数行上にある必要があります
onebree
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.