Obtener una lista de carpetas en un directorio

90

¿Cómo obtengo una lista de las carpetas que existen en un directorio determinado con ruby?

Dir.entries() parece cercano pero no sé cómo limitarlo solo a carpetas.

0xC0DEFACE
fuente

Respuestas:

71

Jordan está cerca, pero Dir.entriesno devuelve el camino completo que File.directory?esperaba. Prueba esto:

 Dir.entries('/your_dir').select {|entry| File.directory? File.join('/your_dir',entry) and !(entry =='.' || entry == '..') }
scottd
fuente
3
Tenga en cuenta que esto le permitirá obtener todos los directorios, incluidos los ocultos, así como '.'(directorio actual) y '..'(padre del directorio actual). En la mayoría de los casos, desea eliminar al menos esos dos.
Telemachus
Prefiero este ... Dir.entries(root).select { |entry| File.directory? File.join(root, entry) and not entry.in? %w[. ..]}
Victor
Pero encontré una solución mucho más clara y concisa, usando Dir.glob.
Victor
Esto es objetivamente peor que Dir.glob()como se ve en la otra respuesta; recomiendo encarecidamente hacer eso en lugar de esto
Dasmowenator
106

Encontré esto más útil y fácil de usar:

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

obtiene todas las carpetas del directorio actual, excluidas .y ...

Para carpetas recurrentes, simplemente use **en lugar de *.

La Dir.globlínea también se puede pasar Dir.chdircomo un bloque:

Dir.chdir('/destination directory') do
  Dir.glob('*').select { |f| File.directory? f }
end
Emiliano Poggi
fuente
17
Para carpetas recurrentes, debe usar **/*en lugar de *.
mkmurray
1
Simple y mejor. Gracias
Biswajit Das
Excelente respuesta.
Retroriff
47

En mi opinión, Pathnamees mucho más adecuado para nombres de archivo que cadenas simples.

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

Esto le da una matriz de todos los directorios en ese directorio como objetos Pathname.

Si quieres tener cuerdas

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

Si directory_namefuera absoluto, estas cadenas también lo son.

johannes
fuente
otra razón para usar Pathnamees que elimina de forma automática ., ..y los archivos como proprietery.DS_Store
rweng
3
más concisamente: Pathname.new (somepath) .children.select (&: directory?)
ablarg
19

Busque de forma recursiva todas las carpetas en un directorio determinado:

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

Versión no recursiva:

Dir.glob 'certain_directory/*/'

Nota: Dir.[]funciona como Dir.glob.

Bohr
fuente
¿Cómo haría la búsqueda de archivos recursiva y no recursiva usando la misma lógica? ¿Y cómo archivos y carpetas recursivos y no recursivos?
píxel
4
directory = 'Folder'
puts Dir.entries(directory).select { |file| File.directory? File.join(directory, file)}
Markus
fuente
4

Puede utilizar File.directory?desde elFileTest módulo para averiguar si un archivo es un directorio. La combinación de esto con Dir.entrieshace que sea agradable (ish) -liner:

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

Editar: actualizado según la corrección de ScottD.

Jordan corriendo
fuente
3

Con este, puede obtener la matriz de una ruta completa a sus directorios , subdirectorios , subsubdirectorios de forma recursiva. Usé ese código para cargar ansiosamente estos archivos dentro del config/applicationarchivo.

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

Además, no necesitamos lidiar con lo aburrido .y ..más. La respuesta aceptada necesitaba lidiar con ellos.

Víctor
fuente
1
Dir.glob('/your_dir').reject {|e| !File.directory?(e)}
msangui
fuente
1
O, en lugar de reject !,select
Financia la demanda de Monica el
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
fuente
1

Para una solución genérica que probablemente desee utilizar

Dir.glob(File.expand_path(path))

Esto funcionará con rutas como ~/*/(todas las carpetas dentro de su directorio personal).

este es mi diseño
fuente
¡Gracias! Esto es muy útil.
Retroriff
1

Podemos combinar la respuesta de Borh y respuesta de Johannes a conseguir absolutamente una solución elegante para obtener los nombres de directorio en una carpeta.

# 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
fuente
1

Solo las carpetas ('.' Y '..' están excluidas):

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

Carpetas y archivos:

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

Iwan B.
fuente
0

Creo que puede probar cada archivo para ver si es un directorio con FileTest.directory? (file_name). Consulte la documentación de FileTest para obtener más información.

matekm
fuente