ซับเดียวเพื่อแสดงรายการไดเรกทอรีซ้ำใน Ruby?


98

วิธีที่เร็วที่สุดและเหมาะสมที่สุดในการรับอาร์เรย์ของไดเร็กทอรี (ไม่รวมไฟล์) ใน Ruby คืออะไร

รวมไฟล์ได้อย่างไร?


2
เร็วที่สุดปรับให้เหมาะสมที่สุดและซับเดียวสามารถขัดแย้งกับการอ่าน / บำรุงรักษาได้ และคุณสามารถค้นหาสิ่งนี้ได้โดยใช้เกณฑ์มาตรฐานและการทดสอบอย่างรวดเร็ว
คนดีบุก

คำตอบ:


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

แทนที่จะDir.glob(foo)คุณยังสามารถเขียนDir[foo]( แต่Dir.globยังสามารถใช้บล็อกในกรณีที่มันจะให้ผลผลิตแต่ละเส้นทางแทนการสร้างอาร์เรย์)

Ruby Glob เอกสาร


10
ใช้Dir.glob("**/")เว้นแต่คุณต้องการ symlinks ด้วย
johannes

6
ไฟล์และไดเรกทอรีที่ซ่อนอยู่ล่ะ?
alediaferia

6
หากต้องการรวม dotfiles ในผลการแข่งขันให้ใช้File::FNM_DOTMATCHแฟล็ก
x-yuri

2
ขอบคุณ @ x-yuri! แฟDir.glob("**/*", File::FNM_DOTMATCH)
ล็ก

2
นี่คือเอกสาร: ruby-doc.org/core-2.2.0/Dir.html#method-c-glob
stephen.hanson

53

ฉันเชื่อว่าไม่มีวิธีแก้ปัญหาใดที่เกี่ยวข้องกับไดเรกทอรีที่ซ่อนอยู่ (เช่น '.test'):

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

Find.find('/tmp').collect {|_|_}เป็นประโยชน์สำหรับฉัน
Alexander Bird

ระวังด้วย Find มันไม่เป็นไปตาม symlinks: 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
เท็จ: Dir.glob ("# {DIRECTORY} / ** / * /"). map {| directory | Pathname.new (ไดเรกทอรี)}
Robert Ross

ใครสามารถอธิบายend.select {}.flatten()ส่วนนี้? ฉันชอบฟังก์ชั่นโดยรวม ดูเหมือนว่าจะสร้างอาร์เรย์อาร์เรย์? เป็นไปได้ไหมที่จะทำelseifส่วนด้วย: rec_path(child, file) << child.to_sเพื่อให้คุณสามารถกำหนดให้กับอาร์เรย์และรับอาร์เรย์ของสตริงได้ ขอบคุณ!
MCP

7

ดังที่ระบุไว้ในคำตอบอื่น ๆ ที่นี่คุณสามารถDir.globใช้ได้ โปรดทราบว่าโฟลเดอร์อาจมีอักขระแปลก ๆ มากมายอยู่ในโฟลเดอร์และอาร์กิวเมนต์ 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 กี่บรรทัดเพื่อให้ได้ผลลัพธ์เดียวกัน


14
ลงคะแนนสำหรับการคัดลอกวางโดยตรงจากmustap.com/rubyzone_post_162_recursive-directory-listingโดยไม่อ้างแหล่งที่มา ...
eckza

@kivetros ฉันแก้ไขคำตอบเพื่อรวมลิงก์เวอร์ชันที่เก็บถาวร :-)
onebree

0

แม้ว่าจะไม่ใช่วิธีแก้ปัญหาแบบบรรทัดเดียว แต่ฉันคิดว่านี่เป็นวิธีที่ดีที่สุดในการใช้การโทรด้วยทับทิม

ขั้นแรกให้ลบไฟล์ทั้งหมดแบบวนซ้ำ
ครั้งที่สองลบไดเร็กทอรีว่างทั้งหมด

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

3
เขา / เธอไม่ต้องการลบไฟล์ / ไดเรกทอรี
Darek Nędza

จะทำอย่างไรกับทั้งไฟล์ + ไดเร็กทอรีในบรรทัดเดียว
vipin8169

0

นี่คือตัวอย่างที่รวมการค้นพบไดเร็กทอรีโปรเจ็กต์ Rails กับ Dir.glob:

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

ฉันลองสิ่งนี้ >> config.assets.paths << Rails.root.join("app", "assets", "*")แต่ยังไม่เห็นโฟลเดอร์ย่อยและไฟล์ในโฟลเดอร์ assets โดยRails.application.config.assets.paths
vipin8169

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

จุดกลับศูนย์ใช้ขนาดกะทัดรัด


1
นี่ไม่หรูหราเกินไปและจะต้องมีอีกสองสามบรรทัดจึงจะเป็นเช่นนั้น
onebree
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.