Pobieranie listy folderów w katalogu

90

Jak uzyskać listę folderów, które istnieją w określonym katalogu z ruby?

Dir.entries() wygląda blisko, ale nie wiem, jak ograniczyć tylko do folderów.

0xC0DEFACE
źródło

Odpowiedzi:

71

Jordan jest blisko, ale Dir.entriesnie zwraca pełnej ścieżki, której się File.directory?oczekuje. Spróbuj tego:

 Dir.entries('/your_dir').select {|entry| File.directory? File.join('/your_dir',entry) and !(entry =='.' || entry == '..') }
scottd
źródło
3
Zauważ, że dostaniesz wszystkie katalogi, w tym ukryte, a także '.'(katalog bieżący) i '..'(katalog macierzysty bieżącego katalogu). W większości przypadków chcesz usunąć co najmniej te dwa.
Telemachus
Wolę ten ... Dir.entries(root).select { |entry| File.directory? File.join(root, entry) and not entry.in? %w[. ..]}
Victor,
Ale podsumowałem rozwiązanie znacznie bardziej przejrzyste i zwięzłe, używając Dir.glob.
Victor
Jest to po prostu obiektywnie gorsze niż to, Dir.glob()co widać w drugiej odpowiedzi - zdecydowanie polecam zrobienie tego zamiast tego
Dasmowenator
105

Uważam, że to bardziej przydatne i łatwe w użyciu:

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

pobiera wszystkie foldery w bieżącym katalogu, wykluczone .i ...

Aby powtarzać foldery, po prostu użyj **zamiast *.

Dir.globLinia może być również przekazywane Dir.chdirjako blok:

Dir.chdir('/destination directory') do
  Dir.glob('*').select { |f| File.directory? f }
end
Emiliano Poggi
źródło
17
Aby powtarzać foldery, musisz użyć **/*zamiast *.
mkmurray
1
Proste i najlepsze. Dziękuję
Biswajit Das
1
Doskonała odpowiedź.
retroryf
47

Moim zdaniem Pathnameznacznie lepiej nadaje się do nazw plików niż zwykłe ciągi.

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

To daje tablicę wszystkich katalogów w tym katalogu jako obiekty Pathname.

Jeśli chcesz mieć struny

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

Gdyby directory_namebyło absolutne, te ciągi też są absolutne.

johannes
źródło
Innym powodem korzystania Pathnamejest to, że automatycznie usuwa ., ..a pliki proprietery jak.DS_Store
rweng
3
bardziej zwięźle: Pathname.new (jakaś ścieżka) .children.select (&: katalog?)
ablarg
19

Rekurencyjnie znajdź wszystkie foldery w określonym katalogu:

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

Wersja nierekurencyjna:

Dir.glob 'certain_directory/*/'

Uwaga: Dir.[]działa jak Dir.glob.

Bohr
źródło
Jak można znaleźć pliki rekurencyjne i nierekurencyjne przy użyciu tej samej logiki? A jak rekurencyjne i nierekurencyjne pliki i foldery?
piksel
4
directory = 'Folder'
puts Dir.entries(directory).select { |file| File.directory? File.join(directory, file)}
Markus
źródło
4

Możesz użyć File.directory?z FileTestmodułu, aby dowiedzieć się, czy plik jest katalogiem. Połączenie tego z Dir.entriestworzy fajną (ish) -liner:

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

Edycja: Zaktualizowano zgodnie z poprawką ScottD.

Jordan Running
źródło
3

Z tym jednym, można uzyskać tablicę z pełną ścieżką do swoich katalogów , podkatalogów , subsubdirectories w rekurencyjnej sposób. Użyłem tego kodu, aby chętnie załadować te pliki do config/applicationpliku.

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

Ponadto nie musimy zajmować się nudne .i ..już. Zaakceptowana odpowiedź musiała poradzić sobie z nimi.

Zwycięzca
źródło
1
Dir.glob('/your_dir').reject {|e| !File.directory?(e)}
msangui
źródło
1
Albo zamiast reject !,select
Pozew FUND Moniki
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
źródło
1

Dla ogólnego rozwiązania, którego prawdopodobnie chcesz użyć

Dir.glob(File.expand_path(path))

Będzie to działać ze ścieżkami takimi jak ~/*/(wszystkie foldery w twoim katalogu domowym).

to mój projekt
źródło
Dzięki! To jest bardzo pomocne.
retroryf
1

Możemy łączyć odpowiedź Borh za i odpowiedzi Johannes' , aby uzyskać dość eleganckie rozwiązanie do coraz nazwy katalogów w folderze.

# 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
źródło
1

Tylko foldery („.” I „..” są wykluczone):

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

Foldery i pliki:

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

Iwan B.
źródło
0

Myślę, że możesz przetestować każdy plik, aby sprawdzić, czy jest to katalog z rozszerzeniem FileTest.directory? (file_name). Zobacz dokumentację FileTest, aby uzyskać więcej informacji.

matekm
źródło