การรับรายชื่อโฟลเดอร์ในไดเร็กทอรี


92

ฉันจะรับรายชื่อโฟลเดอร์ที่มีอยู่ในไดเร็กทอรีที่มีทับทิมได้อย่างไร

Dir.entries() ดูใกล้ ๆ แต่ไม่รู้จะ จำกัด เฉพาะโฟลเดอร์ได้อย่างไร

คำตอบ:


72

จอร์แดนใกล้ แต่Dir.entriesกลับไม่เต็มเส้นทางที่File.directory?คาดหวัง ลองสิ่งนี้:

 Dir.entries('/your_dir').select {|entry| File.directory? File.join('/your_dir',entry) and !(entry =='.' || entry == '..') }

3
โปรดทราบว่าสิ่งนี้จะทำให้คุณได้รับไดเร็กทอรีทั้งหมดรวมถึงไดเร็กทอรีที่ซ่อนอยู่ตลอดจน'.'(ไดเร็กทอรีปัจจุบัน) และ'..'(พาเรนต์ของไดเร็กทอรีปัจจุบัน) ในกรณีส่วนใหญ่คุณต้องการลบทั้งสองอย่างเป็นอย่างน้อย
Telemachus

ฉันชอบอันนี้มากกว่า ... Dir.entries(root).select { |entry| File.directory? File.join(root, entry) and not entry.in? %w[. ..]}
วิกเตอร์

แต่ฉันสรุปวิธีแก้ปัญหาที่ชัดเจนและรวบรัดมากขึ้นโดยใช้Dir.glob.
วิกเตอร์

นี่เป็นเพียงสิ่งที่แย่กว่าDir.glob()ที่เห็นในคำตอบอื่น ๆ - ฉันขอแนะนำอย่างยิ่งให้ทำเช่นนั้นแทนสิ่งนี้
Dasmowenator

105

ฉันพบว่าสิ่งนี้มีประโยชน์และใช้งานง่ายกว่า:

Dir.chdir('/destination_directory')
Dir.glob('*').select {|f| File.directory? f}

ได้รับโฟลเดอร์ทั้งหมดในไดเร็กทอรีปัจจุบันยกเว้น.และ...

ในการเรียกคืนโฟลเดอร์ให้ใช้**แทน*ไฟล์.

Dir.globสายนอกจากนี้ยังสามารถส่งผ่านไปยังDir.chdirเป็นบล็อก:

Dir.chdir('/destination directory') do
  Dir.glob('*').select { |f| File.directory? f }
end

17
ในการเรียกคืนโฟลเดอร์คุณต้องใช้**/*แทน*ไฟล์.
mkmurray

1
ง่ายและดีที่สุด ขอบคุณ
Biswajit Das

1
คำตอบที่ยอดเยี่ยม
retroriff

47

ในความคิดของฉันPathnameเหมาะกับชื่อไฟล์มากกว่าสตริงธรรมดา

require "pathname"
Pathname.new(directory_name).children.select { |c| c.directory? }

สิ่งนี้ทำให้คุณมีอาร์เรย์ของไดเร็กทอรีทั้งหมดในไดเร็กทอรีนั้นเป็นออบเจ็กต์ Pathname

หากคุณต้องการมีสตริง

Pathname.new(directory_name).children.select { |c| c.directory? }.collect { |p| p.to_s }

ถ้าdirectory_nameเป็นค่าสัมบูรณ์สตริงเหล่านี้ก็เป็นค่าสัมบูรณ์เช่นกัน


เหตุผลในการใช้อีกPathnameก็คือว่ามันลบโดยอัตโนมัติ., ..และไฟล์ proprietery เช่น.DS_Store
rweng

3
tersely มากขึ้น: Pathname.new (somepath) .children.select (&: directory?)
ablarg

19

ค้นหาโฟลเดอร์ทั้งหมดซ้ำ ๆ ภายใต้ไดเรกทอรีบางรายการ:

Dir.glob 'certain_directory/**/*/'

เวอร์ชันที่ไม่เรียกซ้ำ:

Dir.glob 'certain_directory/*/'

หมายเหตุ: Dir.[]ทำงานเหมือนDir.glob.


คุณจะค้นหาไฟล์แบบเรียกซ้ำและไม่เรียกซ้ำได้อย่างไรโดยใช้ตรรกะเดียวกัน และไฟล์และโฟลเดอร์แบบเรียกซ้ำและไม่เรียกซ้ำได้อย่างไร?
พิกเซล


4

คุณสามารถใช้File.directory?จากFileTestโมดูลเพื่อดูว่าไฟล์เป็นไดเร็กทอรีหรือไม่ การรวมสิ่งนี้เข้ากับDir.entriesmake for a nice (ish) -liner:

directory = 'some_dir'
Dir.entries(directory).select { |file| File.directory?(File.join(directory, file)) }

แก้ไข:อัปเดตตามการแก้ไขของ ScottD


3

กับคนนี้คุณจะได้รับอาร์เรย์ของที่เส้นทางแบบเต็มไปยังไดเรกทอรี , ไดเรกทอรี , subsubdirectoriesในทาง recursive ฉันใช้รหัสนั้นเพื่อโหลดไฟล์เหล่านี้ภายในconfig/applicationไฟล์อย่างกระตือรือร้น

Dir.glob("path/to/your/dir/**/*").select { |entry| File.directory? entry }

นอกจากนี้เราไม่ต้องการจัดการกับสิ่งที่น่าเบื่อ.และ..อีกต่อไป คำตอบที่ได้รับการยอมรับจำเป็นสำหรับการจัดการกับพวกเขา




1

สำหรับโซลูชันทั่วไปคุณอาจต้องการใช้

Dir.glob(File.expand_path(path))

ซึ่งจะใช้ได้กับพา ธ เช่น~/*/(โฟลเดอร์ทั้งหมดในโฮมไดเร็กทอรีของคุณ)


ขอบคุณ! สิ่งนี้มีประโยชน์มาก
retroriff

1

เราสามารถรวมคำตอบของ Borhและคำตอบของjohannesเข้าด้วยกันเพื่อให้ได้วิธีการแก้ปัญหาที่ยอดเยี่ยมในการรับชื่อไดเรกทอรีในโฟลเดอร์

# user globbing to get a list of directories for a path
base_dir_path = ''
directory_paths = Dir.glob(File.join(base_dir_path, '*', ''))

# or recursive version:
directory_paths = Dir.glob(File.join(base_dir_path, '**', '*', ''))

# cast to Pathname
directories = directory_paths.collect {|path| Pathname.new(path) }

# return the basename of the directories
directory_names = directories.collect {|dir| dir.basename.to_s }


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