Abrufen einer Liste von Ordnern in einem Verzeichnis

89

Wie erhalte ich eine Liste der Ordner, die in einem bestimmten Verzeichnis mit Ruby vorhanden sind?

Dir.entries() sieht genau aus, aber ich weiß nicht, wie ich mich nur auf Ordner beschränken soll.

0xC0DEFACE
quelle

Antworten:

71

Jordan ist nah dran, gibt aber Dir.entriesnicht den vollen Weg zurück, den man File.directory?erwartet. Versuche dies:

 Dir.entries('/your_dir').select {|entry| File.directory? File.join('/your_dir',entry) and !(entry =='.' || entry == '..') }
Scottd
quelle
3
Beachten Sie, dass Sie dadurch alle Verzeichnisse erhalten, einschließlich der versteckten sowie '.'(aktuelles Verzeichnis) und '..'(übergeordnetes Verzeichnis des aktuellen Verzeichnisses). In den meisten Fällen möchten Sie mindestens diese beiden entfernen.
Telemachos
Ich bevorzuge dieses ... Dir.entries(root).select { |entry| File.directory? File.join(root, entry) and not entry.in? %w[. ..]}
Victor
Aber ich habe eine Lösung gefunden, die viel klarer und prägnanter ist, indem ich die Dir.glob.
Victor
Dies ist nur objektiv schlimmer als Dir.glob()in der anderen Antwort zu sehen - ich würde dringend empfehlen, dies stattdessen zu tun
Dasmowenator
106

Ich fand das nützlicher und benutzerfreundlicher:

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

Es werden alle Ordner im aktuellen Verzeichnis abgerufen, ausgeschlossen .und ...

Um Ordner zu rekursieren, verwenden Sie einfach **anstelle von *.

Die Dir.globZeile kann auch Dir.chdirals Block übergeben werden:

Dir.chdir('/destination directory') do
  Dir.glob('*').select { |f| File.directory? f }
end
Emiliano Poggi
quelle
17
Um Ordner zu rekursieren, müssen Sie **/*anstelle von verwenden *.
mkmurray
1
Einfach und am besten. Vielen Dank
Biswajit Das
Hervorragende Antwort.
Retroriff
47

Meiner Meinung nach Pathnameist es für Dateinamen viel besser geeignet als für einfache Zeichenfolgen.

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

Dadurch erhalten Sie ein Array aller Verzeichnisse in diesem Verzeichnis als Pfadnamenobjekte.

Wenn Sie Zeichenfolgen haben möchten

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

Wenn directory_nameabsolut, sind diese Zeichenfolgen auch absolut.

johannes
quelle
ein weiterer Grund für die Verwendung Pathnameist , dass es automatisch entfernt ., ..und proprietery Dateien wie.DS_Store
rweng
3
knapper: Pathname.new (somepath) .children.select (&: directory?)
ablarg
19

Suchen Sie rekursiv alle Ordner in einem bestimmten Verzeichnis:

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

Nicht rekursive Version:

Dir.glob 'certain_directory/*/'

Hinweis: Dir.[]funktioniert wie Dir.glob.

Bohr
quelle
Wie würden Sie rekursive und nicht rekursive Dateisuche mit derselben Logik durchführen? Und wie rekursiv und nicht rekursiv Dateien und Ordner?
Pixel
4
directory = 'Folder'
puts Dir.entries(directory).select { |file| File.directory? File.join(directory, file)}
Markus
quelle
4

Sie können anhand File.directory?des FileTestModuls herausfinden, ob eine Datei ein Verzeichnis ist. Die Kombination mit Dir.entriesergibt einen schönen (ish) -Liner:

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

Bearbeiten: Aktualisiert gemäß ScottD-Korrektur.

Jordan läuft
quelle
3

Mit diesem können Sie das Array eines vollständigen Pfads zu Ihren Verzeichnissen , Unterverzeichnissen und Unterverzeichnissen auf rekursive Weise abrufen . Ich habe diesen Code verwendet, um diese Dateien eifrig in die config/applicationDatei zu laden .

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

Darüber hinaus brauchen wir nicht mit den langweiligen beschäftigen .und ..mehr. Die akzeptierte Antwort musste sich mit ihnen befassen.

Sieger
quelle
1
Dir.glob('/your_dir').reject {|e| !File.directory?(e)}
msangui
quelle
1
Oder statt reject !,select
Fonds Monica Strafanzeige
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
quelle
1

Für eine generische Lösung möchten Sie wahrscheinlich verwenden

Dir.glob(File.expand_path(path))

Dies funktioniert mit Pfaden wie ~/*/(alle Ordner in Ihrem Home-Verzeichnis).

Das ist mein Design
quelle
Vielen Dank! Das ist sehr hilfreich.
Retroriff
1

Wir können kombinieren Born Antwort und johannes' Antwort zu bekommen recht eine elegante Lösung zu bekommen , die Verzeichnisnamen in einem Ordner.

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

Nur Ordner ('.' Und '..' sind ausgeschlossen):

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

Ordner und Dateien:

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

Iwan B.
quelle
0

Ich denke, Sie können jede Datei testen, um festzustellen, ob es sich um ein Verzeichnis mit handelt FileTest.directory? (file_name). Weitere Informationen finden Sie in der Dokumentation zu FileTest .

matekm
quelle