Mendapatkan daftar folder dalam sebuah direktori

90

Bagaimana cara mendapatkan daftar folder yang ada di direktori tertentu dengan ruby?

Dir.entries() terlihat dekat tetapi saya tidak tahu cara membatasi ke folder saja.

0xC0DEFACE
sumber

Jawaban:

71

Jordan sudah dekat, tetapi Dir.entriestidak kembali ke jalur penuh yang File.directory?diharapkan. Coba ini:

 Dir.entries('/your_dir').select {|entry| File.directory? File.join('/your_dir',entry) and !(entry =='.' || entry == '..') }
scottd
sumber
3
Perhatikan bahwa ini akan memberi Anda semua direktori, termasuk yang tersembunyi serta '.'(direktori saat ini) dan '..'(induk direktori saat ini). Dalam kebanyakan kasus, Anda ingin menghapus setidaknya keduanya.
Telemakus
Saya lebih suka yang ini ... Dir.entries(root).select { |entry| File.directory? File.join(root, entry) and not entry.in? %w[. ..]}
Victor
Tapi saya menyimpulkan solusi yang jauh lebih jelas dan ringkas, menggunakan Dir.glob.
Victor
Ini secara obyektif lebih buruk daripada yang Dir.glob()terlihat pada jawaban lain - Saya sangat menyarankan untuk melakukan itu saja daripada ini
Dasmowenator
105

Menurut saya ini lebih berguna dan mudah digunakan:

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

itu mendapat semua folder di direktori saat ini, dikecualikan .dan.. .

Untuk mengulang folder, cukup gunakan **sebagai pengganti* .

The Dir.globgaris juga dapat dikirimkan ke Dir.chdirsebagai blok:

Dir.chdir('/destination directory') do
  Dir.glob('*').select { |f| File.directory? f }
end
Emiliano Poggi
sumber
17
Untuk mengulang folder, Anda perlu menggunakan **/*sebagai pengganti *.
mkmurray
1
Sederhana dan terbaik. Terima kasih
Biswajit Das
1
Jawaban yang sangat bagus.
retroriff
47

Menurut pendapat saya Pathnamejauh lebih cocok untuk nama file daripada string biasa.

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

Ini memberi Anda larik semua direktori di direktori itu sebagai objek Pathname.

Jika Anda ingin memiliki string

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

Jika directory_namemutlak, string ini juga mutlak.

johannes
sumber
alasan lain untuk menggunakan Pathnameadalah bahwa secara otomatis menghapus ., ..dan file kepemilikan seperti.DS_Store
rweng
3
lebih singkat: Pathname.new (somepath) .children.select (&: directory?)
ablarg
19

Temukan semua folder di bawah direktori tertentu secara rekursif:

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

Versi non-rekursif:

Dir.glob 'certain_directory/*/'

Catatan: Dir.[]berfungsi seperti Dir.glob.

Bohr
sumber
Bagaimana Anda melakukan pencarian file rekursif dan non-rekursif menggunakan logika yang sama? Dan bagaimana file dan folder rekursif dan non-rekursif?
piksel
4
directory = 'Folder'
puts Dir.entries(directory).select { |file| File.directory? File.join(directory, file)}
Markus
sumber
4

Anda dapat menggunakan File.directory?dari FileTestmodul untuk mengetahui apakah file adalah direktori. Menggabungkan ini dengan Dir.entriesmake untuk yang bagus (ish) -liner:

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

Edit: Diperbarui per koreksi ScottD.

Jordan Running
sumber
3

Dengan yang satu ini, Anda bisa mendapatkan array dari path lengkap untuk Anda direktori , subdirektori , subsubdirectories dengan cara rekursif. Saya menggunakan kode itu untuk memuat file-file ini di dalam config/applicationfile.

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

Selain itu kita tidak perlu berurusan dengan yang membosankan .dan ..lagi. Jawaban yang diterima perlu berurusan dengan mereka.

Pemenang
sumber
1
Dir.glob('/your_dir').reject {|e| !File.directory?(e)}
msangui
sumber
1
Atau, bukannya reject !,select
Gugatan Dana Monica
1
$dir_target = "/Users/david/Movies/Camtasia 2/AzureMobileServices.cmproj/media"

Dir.glob("#{$dir_target}/**/*").each do |f| 
  if File.directory?(f)
    puts "#{f}\n"
  end
end
David Douglas
sumber
1

Untuk solusi umum yang mungkin ingin Anda gunakan

Dir.glob(File.expand_path(path))

Ini akan bekerja dengan jalur seperti ~/*/(semua folder dalam direktori home Anda).

ini adalah desainku
sumber
Terima kasih! Ini sangat membantu.
retroriff
1

Kita dapat menggabungkan jawaban Borh dan jawaban johannes untuk mendapatkan solusi yang cukup elegan untuk mendapatkan nama direktori dalam sebuah folder.

# 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 }
br3nt
sumber
1

Hanya folder ('.' Dan '..' yang dikecualikan):

Dir.glob(File.join(path, "*", File::SEPARATOR))

Folder dan file:

Dir.glob(File.join(path, "*"))

Iwan B.
sumber
0

Saya rasa Anda dapat menguji setiap file untuk melihat apakah itu adalah direktori dengan FileTest.directory? (file_name). Lihat dokumentasi FileTest untuk info lebih lanjut.

matekm
sumber