1つのディレクトリ内のすべてのファイルを反復処理します


274

各ファイルでコードのブロックを実行できるように、ルビーでループを作成するにはどうすればよいですか?

私はルビーの初心者で、これを行う方法はループごとに実行することであると結論しました。
rubyファイルは、ループしたいディレクトリとは別のディレクトリから実行されます。

私は試してみましたが、Dir.foreach動作させることができませんでした。


2
それを機能させようとしたときに何が起こったかを特定できますか?あなたが試した正確なコードは何ですか(または、長い場合は関連するチャンク)?どのようなエラーメッセージが表示されましたか?Dir.foreachディレクトリの内容を反復処理するように機能するので、他の多くのことが起こっています。
Telemachus

3
あなただけのディレクトリ内のファイルをしたい場合は、ディレクトリの内容を反復処理する場合、ファイルのためにテストすることを忘れないでください: do_something_with(entry) if File.file?(entry)
グレンはジャックマン

3
'img/*.{jpg,png,gif,jpeg}'複数の拡張機能を取得するために使用します。
Benjamin Crouzier 2013年

OPが4年以上サイトに存在していないため、@ ChrisPetersは残念ながらありそうにありません。
ジョーケネディ

回答:


429

他の人が言ったように、Dir::foreachここは良いオプションです。ただし、Dir::foreachandにDir::entriesは常に.and ..(現在のディレクトリと親ディレクトリ)が含まれることに注意してください。通常はそれらに取り組みたくないので、Dir::each_childまたはDir::childrenma11hew28で提案されているように)または次のように使用できます。

Dir.foreach('/path/to/dir') do |filename|
  next if filename == '.' or filename == '..'
  # Do work on the remaining files & directories
end

Dir::foreachand Dir::entriesDir::each_childおよびand Dir::children)には隠しファイルとディレクトリも含まれます。多くの場合、これで十分ですが、そうでない場合は、スキップして何かを行う必要があります。

または、Dir::glob単純なワイルドカード一致を提供するを調べたい場合があります。

Dir.glob('/path/to/dir/*.rb') do |rb_filename|
  # Do work on files & directories ending in .rb
end

12
Dir.foreachディレクトリに大量のファイルが含まれている場合に使用してください!
Tilo 2013

5
ありがとう!それをさらに改善する小さなmod:next if File.directory? item
mr.buttons

@ mr.buttonsそれは常に正しいことをするわけではありません。時々人々はファイルと同様にディレクトリで働きたいと思う。私は特別なリストを回避するためのコードを与えました、.または..人々がほとんど常にこれら2つを無視したいので。
Telemachus、

3
@Tilo:興味がなくなったので、理由をもう少し詳しく説明してください。:)
mkataja 2015年

11
@mkataja Dir.foreachは(潜在的に巨大な)配列を前もって構築するのではなく、反復します(実行Dir.globします)。したがって、ディレクトリが非常に大きい場合、パフォーマンスに違いが生じる可能性があります。通常の状況では気付かないでしょうが、ストレス状態では、それは絶対に重要です。
Telemachus 2015年

99

これは、読みやすくするための私のお気に入りの方法です。

Dir.glob("*/*.txt") do |my_text_file|
  puts "working on: #{my_text_file}..."
end

さらに、これを拡張して、サブディレクトリ内のすべてのファイルを処理することもできます。

Dir.glob("**/*.txt") do |my_text_file| # note one extra "*"
  puts "working on: #{my_text_file}..."
end

30

Dirには、ディレクトリからすべてのファイルの配列を取得するための短い構文もあります。

Dir['dir/to/files/*'].each do |fname|
    # do something with fname
end

このコードで、ディレクトリがfnameの反復でも使用されないようにするにはどうすればよいですか?
kayleeFrye_onDeck 2017年


13

検索ライブラリは、このタスク専用に設計されています。https//ruby-doc.org/stdlib-2.5.1/libdoc/find/rdoc/Find.html

require 'find'
Find.find(path) do |file|
  # process
end

これは標準のルビーライブラリなので、利用できるはずです


1
File.find与えた任意のパスから始めて、可能な限り再帰的に下降します。OPが望んでいることはわかりません。
Telemachus

そのメソッドにアクセスできないようです-Find.find?この機能を含むライブラリをダウンロードする必要がありますか?
blue-sky

@ user470184:「検索」は標準のRubyライブラリであり、デフォルトのRubyインストールで利用できるはずです。ただし、使用するには「検索が必要」である必要があります。
ファイサル

1
@Faisalすることができます私は次のようにglobパターンをパス*.rbfind()
Ashharハサン

7

私はこれが好きです、それは上記で言及されていません。

require 'pathname'

Pathname.new('/my/dir').children.each do |path|
    puts path
end

利点は、文字列ではなくPathnameオブジェクトを取得することです。これにより、有用な処理を実行して、さらにトラバースできます。


3
Dir.new('/my/dir').each do |name|
  ...
end

1
Dir.new( '/ my / dir')に加えて、Dir.entries( '/ my / dir')もありますが、Dir.foreach()はもう少し簡潔です。
Tin Man

5
@ZEDまた、配列全体を一度に構築しDir.foreachながら反復しDir.entriesます。したがって、ディレクトリが巨大な場合、メモリヒットは少なくなります。(通常は大したことではないでしょうが、それでも...)
Telemachus 2010年

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.