Lấy danh sách các thư mục trong một thư mục


90

Làm cách nào để lấy danh sách các thư mục tồn tại trong một thư mục nhất định bằng ruby?

Dir.entries() nhìn gần nhưng tôi không biết làm thế nào để chỉ giới hạn trong các thư mục.

Câu trả lời:


71

Jordan đã gần, nhưng Dir.entrieskhông trở lại con đường đầy đủ như File.directory?mong đợi. Thử cái này:

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

3
Lưu ý rằng điều này sẽ giúp bạn nhận được tất cả các thư mục, bao gồm cả những thư mục ẩn cũng như '.'(thư mục hiện tại) và '..'(thư mục mẹ của thư mục hiện tại). Trong hầu hết các trường hợp, bạn muốn loại bỏ ít nhất hai điều đó.
Telemachus

Tôi thích cái này ... Dir.entries(root).select { |entry| File.directory? File.join(root, entry) and not entry.in? %w[. ..]}
Victor

Nhưng tôi giới hạn một giải pháp rõ ràng và ngắn gọn hơn nhiều, sử dụng Dir.glob.
Victor

Đây chỉ là một cách khách quan tồi tệ hơn Dir.glob()như đã thấy trong các câu trả lời khác - Tôi rất muốn khuyên bạn nên chỉ làm điều đó thay vì điều này
Dasmowenator

106

Tôi thấy điều này hữu ích và dễ sử dụng hơn:

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

nó nhận tất cả các thư mục trong thư mục hiện tại, loại trừ ....

Để đệ quy các thư mục chỉ cần sử dụng **thay thế *.

Các Dir.globdòng cũng có thể được chuyển tới Dir.chdirnhư một khối:

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

17
Để đệ quy các thư mục, bạn cần sử dụng **/*thay thế cho *.
mkmurray

1
Đơn giản và tốt nhất. Cảm ơn bạn
Biswajit Das

Câu trả lời xuất sắc.
retroriff

47

Theo ý kiến ​​của tôi, Pathnametên tệp phù hợp hơn nhiều so với chuỗi đơn giản.

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

Điều này cung cấp cho bạn một mảng tất cả các thư mục trong thư mục đó dưới dạng các đối tượng Pathname.

Nếu bạn muốn có chuỗi

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

Nếu directory_namelà tuyệt đối, các chuỗi này cũng là tuyệt đối.


một lý do khác cho việc sử dụng Pathnamelà nó tự động loại bỏ ., ..và các tập tin proprietery như.DS_Store
rweng

3
ngắn gọn hơn: Pathname.new (somepath) .children.select (&: thư mục?)
ablarg

19

Tìm đệ quy tất cả các thư mục trong một thư mục nhất định:

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

Phiên bản không đệ quy:

Dir.glob 'certain_directory/*/'

Lưu ý: Dir.[]hoạt động như thế nào Dir.glob.


Bạn sẽ làm cách nào để tìm tệp đệ quy và không đệ quy bằng cách sử dụng cùng một logic? Và tệp và thư mục đệ quy và không đệ quy như thế nào?
pixel

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

4

Bạn có thể sử dụng File.directory?từ FileTestmô-đun để tìm xem tệp có phải là một thư mục hay không. Kết hợp cái này với Dir.entriestạo ra một cái đẹp (ish) -liner:

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

Chỉnh sửa: Đã cập nhật mỗi lần chỉnh sửa của ScottD.


3

Với thế này, bạn có thể nhận được các mảng của một đường dẫn đầy đủ để bạn thư mục , thư mục con , subsubdirectories một cách đệ quy. Tôi đã sử dụng mã đó để tải các tệp này vào bên trong config/applicationtệp.

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

Ngoài ra, chúng ta không cần phải đối phó với sự nhàm chán ...nữa. Câu trả lời được chấp nhận cần thiết để đối phó với chúng.



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

1

Đối với một giải pháp chung, bạn có thể muốn sử dụng

Dir.glob(File.expand_path(path))

Điều này sẽ hoạt động với các đường dẫn như ~/*/(tất cả các thư mục trong thư mục chính của bạn).


Cảm ơn! Điều này rất hữu ích.
hồi tố

1

Chúng ta có thể kết hợp câu trả lời của Borhcâu trả lời của johannes để có được một giải pháp khá hữu ích để lấy tên thư mục trong một thư mục.

# 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 }

1

Chỉ các thư mục ('.' Và '..' bị loại trừ):

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

Thư mục và tệp:

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


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.