Tek bir dizindeki her dosya için yineleme


274

Her dosyada bir kod bloğu yürütebilmem için Ruby'de bir döngü nasıl yazarım?

Ruby'ye yeniyim ve bunu yapmanın yolunun her döngü için bir sonuç olduğu sonucuna vardım.
Ruby dosyası, üzerinden geçmek istediğim dizinden farklı bir dizinden yürütülür.

Denedim Dir.foreachve işe yaramadım.


2
Çalıştırmaya çalıştığınızda ne olduğunu belirtebilir misiniz? Hangi kodu tam olarak denediniz (veya uzunsa ilgili yığın)? Hangi hata mesajlarını aldınız? Dir.foreachbir dizinin içeriğini yinelemek için çalışır, bu yüzden başka bir şey oluyor.
Telemachus

3
Yalnızca dizininizdeki dosyaları istiyorsanız, dizin içeriği üzerinde yineleme yaparken dosyaları test etmeyi unutmayın: do_something_with(entry) if File.file?(entry)
glenn jackman

3
'img/*.{jpg,png,gif,jpeg}'Birden çok uzantıyı yakalamak için kullanın .
Benjamin Crouzier

OP dört yıldan fazla bir süredir sitede bulunmadığı için @ChrisPeters maalesef olası görünmüyor.
Joe Kennedy

Yanıtlar:


429

Diğerlerinin söylediği gibi, Dir::foreachburada iyi bir seçenektir. Ancak, not olduğunu Dir::foreachve Dir::entriesher zaman yer alacak .ve ..(mevcut ve üst dizinleri). Genellikle üzerinde çalışmak istemezsiniz, bu nedenle Dir::each_childveya Dir::children( ma11hew28 tarafından önerildiği gibi ) kullanabilir veya böyle bir şey yapabilirsiniz:

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

Dir::foreachve Dir::entries( Dir::each_childveDir::children ) da gizli dosyaları ve dizinleri içerir. Genellikle istediğiniz budur, ancak değilse, atlamak için bir şeyler yapmanız gerekir.

Alternatif olarak, Dir::globbasit joker karakter eşleşmesini sağlayan şunlara bakmak isteyebilirsiniz :

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

12
Dir.foreachDizin çok sayıda dosya içeriyorsa kullanın !
Tilo

5
Teşekkürler! Daha da iyi hale getirmek için küçük mod:next if File.directory? item
mr

@ mr.buttons Bu her zaman doğru olanı yapmayacaktır. Bazen insanlar dizinlerin yanı sıra dosyalar üzerinde de çalışmak isterler. Özel listelerden kaçınmak için kod verdim .ya da ..insanlar neredeyse her zaman bu ikisini göz ardı etmek istediklerinden.
Telemachus

3
@Tilo: sadece ilgisiz, neden biraz daha ayrıntılı açıklamak için bakım? :)
mkataja

11
@mkataja Dir.foreach(muhtemelen) büyük bir (potansiyel olarak büyük) dizi oluşturmak yerine yineliyor Dir.glob. Dizin gerçekten çok büyükse, bir performans farkı yaratabilir. Normal koşullar altında fark etmezsiniz, ancak stres koşulları altında kesinlikle önemli olabilir.
Telemachus

99

Bu, okunması kolay olmanın en sevdiğim yöntemidir:

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

Ve bunu alt dizinlerdeki tüm dosyalar üzerinde çalışacak şekilde genişletebilirsiniz:

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

30

Dizin ayrıca dizindeki tüm dosyaların bir dizisini almak için daha kısa sözdizimine sahiptir:

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

Bu kodda yer alan dizinlerin fnameyinelemeleriyle de kullanılmasını engeller ?
kayleeFrye_onDeck

26
Dir.foreach("/home/mydir") do |fname|
  puts fname
end

2
Alternatif olarak Dir # [] veya Dir # glob kullanın
Ryan Bigg

13

Bulma kütüphanesi bu görev için özel olarak tasarlanmıştır: https://ruby-doc.org/stdlib-2.5.1/libdoc/find/rdoc/Find.html

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

Bu standart bir yakut kütüphanesidir, bu yüzden mevcut olmalıdır


1
File.findsize verdiğiniz her yoldan başlayarak, yinelemeli olarak olabildiğince aşağı iner. OP'nin bunu istediğinden emin değilim.
Telemachus

Bu yönteme erişimi yok gibi görünüyor - Find.find? Bu işlevselliği içeren bir kütüphane indirmem gerekiyor mu?
blue-sky

@ user470184: "Bul" standart bir ruby ​​kütüphanesidir ve varsayılan ruby ​​yüklemesi ile kullanılabilir olmalıdır. Ancak, kullanabilmeniz için "bul" yapmanız gerekir.
Faysal

1
@Faisal Can I gibi glob desenleri geçmesi *.rbiçinfind()
Ashhar Hasan

7

Bunu beğendim, bu yukarıda belirtilmemiş.

require 'pathname'

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

Bunun yararı, yararlı şeyler yapabileceğiniz ve daha fazla ilerleyebileceğiniz bir dize yerine bir Pathname nesnesi almanızdır.


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

1
Dir.new'e ('/ my / dir') ek olarak Dir.entries ('/ my / dir') de var ama Dir.foreach () biraz daha özlü.
Tin Man

5
@ZED Ayrıca tüm diziyi aynı anda oluştururken Dir.foreachyineler Dir.entries. Dizin çok büyükse, hafıza isabetinden daha azdır. (Genellikle büyük bir anlaşma değil, ama yine de ...)
Telemachus

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.