Получение списка папок в каталоге

90

Как мне получить список папок, которые существуют в определенном каталоге с помощью ruby?

Dir.entries() похоже, но я не знаю, как ограничиться только папками.

0xC0DEFACE
источник

Ответы:

71

Джордан близок, но Dir.entriesне возвращается по ожидаемому пути File.directory?. Попробуй это:

 Dir.entries('/your_dir').select {|entry| File.directory? File.join('/your_dir',entry) and !(entry =='.' || entry == '..') }
Скотт
источник
3
Обратите внимание, что это даст вам все каталоги, включая скрытые, а также '.'(текущий каталог) и '..'(родительский каталог). В большинстве случаев вы хотите удалить хотя бы эти два.
Телемах,
Я предпочитаю этот ... Dir.entries(root).select { |entry| File.directory? File.join(root, entry) and not entry.in? %w[. ..]}
Виктор
Но я нашел более ясное и емкое решение, используя расширение Dir.glob.
Виктор
Это просто объективно хуже, чем Dir.glob()в другом ответе - я настоятельно рекомендую просто сделать это вместо этого
Dasmowenator
105

Я нашел это более полезным и простым в использовании:

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

он получает все папки в текущем каталоге, исключенные .и ...

Для рекурсии папок просто используйте **вместо *.

Dir.globЛиния также может быть передана в Dir.chdirкачестве блока:

Dir.chdir('/destination directory') do
  Dir.glob('*').select { |f| File.directory? f }
end
Эмилиано Поджи
источник
17
Для рекурсии папок вам необходимо использовать **/*вместо *.
mkmurray
1
Просто и лучше. Спасибо
Бисваджит Дас
1
Отличный ответ.
ретрорифф
47

На мой взгляд, Pathnameон намного лучше подходит для имен файлов, чем для простых строк.

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

Это дает вам массив всех каталогов в этом каталоге в виде объектов Pathname.

Если вы хотите иметь струны

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

Если directory_nameбыло абсолютным, эти строки тоже абсолютны.

Йоханнес
источник
еще одна причина для использования в Pathnameтом , что он автоматически удаляет ., ..и proprietery файлы , такие как.DS_Store
rweng
3
короче: Pathname.new (somepath) .children.select (&: directory?)
ablarg
19

Рекурсивно найти все папки в определенном каталоге:

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

Безрекурсивная версия:

Dir.glob 'certain_directory/*/'

Примечание: Dir.[]работает вроде Dir.glob.

Бор
источник
Как бы вы выполняли рекурсивный и нерекурсивный поиск файлов, используя ту же логику? А как рекурсивные и нерекурсивные файлы и папки?
pixel
4
directory = 'Folder'
puts Dir.entries(directory).select { |file| File.directory? File.join(directory, file)}
Маркус
источник
4

Вы можете использовать File.directory?из FileTestмодуля, чтобы узнать, является ли файл каталогом. Сочетание этого с Dir.entriesприятным (иш) лайнером:

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

Изменить: Обновлено в соответствии с исправлением ScottD.

Джордан Бег
источник
3

С этим, вы можете получить массив на полный путь к вашим каталогам , подкаталоги , рекурсивно рекурсивным образом. Я использовал этот код, чтобы загрузить эти файлы внутрь config/applicationфайла.

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

Вдобавок нам не нужно заниматься скучным .и ..прочим. Принятый ответ нужно было разобраться с ними.

Виктор
источник
1
Dir.glob('/your_dir').reject {|e| !File.directory?(e)}
msangui
источник
1
Или, вместо того reject !,select
Иск Фонда Моники
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

Для общего решения вы, вероятно, захотите использовать

Dir.glob(File.expand_path(path))

Это будет работать с такими путями, как ~/*/(все папки в вашем домашнем каталоге).

это
источник
Благодарность! Это очень полезно.
ретрофф
1

Мы можем объединить ответ Borh в и ответ Йоханнеса получить довольно элегантное решение , чтобы получить имена каталогов в папке.

# 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
источник
1

Только папки (исключены "." И ".."):

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

Папки и файлы:

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

Иван Б.
источник
0

Я думаю, вы можете протестировать каждый файл, чтобы убедиться, что это каталог с расширением FileTest.directory? (file_name). Дополнительную информацию см. В документации по FileTest .

матекм
источник