Obter uma lista de pastas em um diretório


90

Como faço para obter uma lista das pastas que existem em um determinado diretório com ruby?

Dir.entries() parece perto, mas não sei como limitar apenas a pastas.

Respostas:


71

Jordan está perto, mas Dir.entriesnão retorna o caminho completo que File.directory?espera. Experimente isto:

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

3
Observe que isso irá obter todos os diretórios, incluindo os ocultos, bem como '.'(diretório atual) e '..'(pai do diretório atual). Na maioria dos casos, você deseja remover pelo menos esses dois.
Telêmaco

Eu prefiro este ... Dir.entries(root).select { |entry| File.directory? File.join(root, entry) and not entry.in? %w[. ..]}
Victor

Mas encontrei uma solução muito mais clara e sucinta, usando o Dir.glob.
Victor

Isso é apenas objetivamente pior do Dir.glob()que visto na outra resposta - eu recomendo fortemente apenas fazer isso em vez disso
Dasmowenator

106

Achei isso mais útil e fácil de usar:

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

ele obtém todas as pastas no diretório atual, excluídas .e.. .

Para recobrir pastas, basta usar **no lugar de* .

A Dir.globlinha também pode ser passada Dir.chdircomo um bloco:

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

17
Para reciclar pastas, você precisa usar **/*no lugar de *.
mkmurray

1
Simples e melhor. Obrigado
Biswajit Das

Excelente resposta.
retroriff

47

Em minha opinião, Pathnameé muito mais adequado para nomes de arquivos do que strings simples.

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

Isso fornece uma matriz de todos os diretórios naquele diretório como objetos Pathname.

Se você quiser ter cordas

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

Se directory_namefosse absoluto, essas strings também seriam absolutas.


outra razão para usar Pathname é que ele remove automaticamente ., ..e arquivos de propriedade como.DS_Store
rweng

3
mais concisamente: Pathname.new (somepath) .children.select (&: directory?)
ablarg

19

Encontre recursivamente todas as pastas em um determinado diretório:

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

Versão não recursiva:

Dir.glob 'certain_directory/*/'

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


Como você localizaria arquivos recursivos e não recursivos usando a mesma lógica? E como arquivos e pastas recursivos e não recursivos?
pixel

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

4

Você pode usar File.directory?o FileTestmódulo para descobrir se um arquivo é um diretório. Combinar isso com Dir.entriesfaz um belo forro (ish):

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

Edit: Atualizado de acordo com a correção de ScottD.


3

Com este, você pode obter a matriz de um caminho completo para seus diretórios , subdiretórios , subsubdiretórios de forma recursiva. Usei esse código para carregar ansiosamente esses arquivos dentro do config/applicationarquivo.

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

Além disso, não precisamos lidar com o chato .e ..mais. A resposta aceita precisava lidar com eles.



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

Para uma solução genérica que você provavelmente deseja usar

Dir.glob(File.expand_path(path))

Isso funcionará com caminhos como ~/*/(todas as pastas em seu diretório inicial).


Obrigado! Isso é muito útil.
retroriff de

1

Podemos combinar a resposta de borh e resposta Johannes a ficar bastante uma solução elegante para obter os nomes de diretório em uma pasta.

# 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

Apenas pastas ('.' E '..' são excluídas):

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

Pastas e arquivos:

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


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.