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.

0xC0DEFACE
fonte

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 == '..') }
Scott
fonte
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
Emiliano Poggi
fonte
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.

johannes
fonte
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.

Bohr
fonte
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)}
Markus
fonte
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.

Jordan Running
fonte
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.

Vencedor
fonte
1
Dir.glob('/your_dir').reject {|e| !File.directory?(e)}
msangui
fonte
1
Ou, em vez de reject !,select
Ação do Fundo 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
fonte
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).

thisismydesign
fonte
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 }
br3nt
fonte
1

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

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

Pastas e arquivos:

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

Iwan B.
fonte
0

Acho que você pode testar cada arquivo para ver se é um diretório com FileTest.directory? (file_name). Consulte a documentação do FileTest para obter mais informações.

matekm
fonte