2010-03-03 10 views
86

Jaki jest najszybszy, najbardziej zoptymalizowany, jednolinetowy sposób na uzyskanie tablicy katalogów (z wyjątkiem plików) w Ruby?One-liner do rekurencyjnej listy katalogów w Ruby?

Co z dołączaniem plików?

+1

Najszybsza, najbardziej zoptymalizowana i jednoliniowa może być niezgodna z przeznaczeniem do odczytu/konserwacji. I można to znaleźć za pomocą testu porównawczego i szybkiego testowania. –

Odpowiedz

147
Dir.glob("**/*/") # for directories 
Dir.glob("**/*") # for all files 

Zamiast można również napisać Dir[foo] (jednak Dir.glob może również przyjąć blok, w którym to przypadku będzie on podawał każdą ścieżkę zamiast tworzenia tablicy).

Ruby Glob Docs

+0

dzięki, brakowało tego końcowego ukośnika. –

+8

użyj 'Dir.glob (" **/")', chyba że chcesz również dowiązań symbolicznych – johannes

+6

Co z ukrytymi plikami i katalogami? – alediaferia

6

Szybkie jeden liner

tylko katalogi

`find -type d`.split("\n") 

katalogi i normalne pliki

`find -type d -or -type f`.split("\n")` 

Czysta piękny rubinowy

require "pathname" 

def rec_path(path, file= false) 
    puts path 
    path.children.collect do |child| 
    if file and child.file? 
     child 
    elsif child.directory? 
     rec_path(child, file) + [child] 
    end 
    end.select { |x| x }.flatten(1) 
end 

# only directories 
rec_path(Pathname.new(dir), false) 
# directories and normal files 
rec_path(Pathname.new(dir), true) 
+1

Fałsz: Dir.glob ("# {DIRECTORY}/**/* /"). Map {| katalog | Pathname.new (directory)} –

+1

@RobertRoss: ?? – johannes

+0

Czy ktoś może wyjaśnić część 'end.select {} .flatten()'? Lubię ogólną funkcję. Wygląda na to, że stworzysz tablicę tablic? Czy byłoby możliwe wykonanie części 'elseif' z:' rec_path (child, file) << child.to_s', aby można było przypisać ją do tablicy i uzyskać tablicę łańcuchów? Dzięki! – MCP

24

Na liście katalogów spróbować

Dir['**/'] 

Lista plików jest trudniejsze, ponieważ w systemie Unix katalogów jest również plik, więc trzeba przetestować na typ lub usunąć wpisy z zwracanej listy, które jest rodzicem innych wpisów.

Dir['**/*'].reject {|fn| File.directory?(fn) } 

I listę wszystkich plików i katalogów po prostu

Dir['**/*'] 
+0

Zauważ, że powiedział "również dołącz pliki", a nie "tylko pliki", więc nie musisz usuwać katalogów. – sepp2k

+1

@ sepp2k Tak, tęskniłem za tą częścią, kiedy grałem z irb. Ale zostawiam to na wypadek, gdyby ktoś mógł wyszukać coś podobnego :-) – MBO

1

W PHP lub innych językach, aby uzyskać zawartość katalogu i wszystkich jego podkatalogów, trzeba napisać kilka wierszy kodu, ale w Ruby zajmuje 2 wiersze:

require 'find' 
Find.find('./') do |f| p f end 

spowoduje wydruk zawartości bieżącego katalogu i wszystkich jego podkatalogów.

lub krótsza, może użyć ’**’ notacji:

p Dir['**/*.*'] 

Ile linie będą pisać w PHP lub Java, aby uzyskać ten sam wynik?

+13

Zwrócono wniosek o skopiowanie bezpośrednio z http://www.mustap.com/rubyzone_post_162_recursive-directory-listing bez cytowania źródła ... – eckza

+0

@kivetros I edytował odpowiedź, aby dołączyć zarchiwizowaną wersję linku :-) – onebree

1

Chociaż nie jest to rozwiązanie jednokierunkowe, uważam, że jest to najlepszy sposób, aby to zrobić za pomocą wywołań ruby.

najpierw usunąć wszystkie pliki rekurencyjnie
drugie usunąć wszystkie puste katalogi

Dir.glob("./logs/**/*").each { |file| File.delete(file) if File.file? file } 
Dir.glob("./logs/**/*/").each { |directory| Dir.delete(directory) } 
+2

On/ona nie chce usuwać plików/katalogów. –

+0

Jak to zrobić dla obu plików + katalog w jednym wierszu? – vipin8169

-1
Dir.open(Dir.pwd).map { |h| (File.file?(h) ? "#{h} - file" : "#{h} - folder") if h[0] != '.' } 

kropki zwracają zerowa, używać kompaktowy

+1

To nie jest zbyt eleganckie i musiałoby być na kilku liniach, aby być tak – onebree

50

wierzę żaden z rozwiązaniami tutaj do czynienia z ukrytych katalogów (np. ".test "):

require 'find' 
Find.find('.') { |e| puts e if File.directory?(e) } 
+0

To jest dokładnie to, czego szukałem. –

+2

Ta odpowiedź zasługuje na najlepszy kredyt. – konsolebox

+0

'Find.find ('/ tmp'). Collect {| _ | _}' Był dla mnie pomocny –

5

Jak zauważono w innych odpowiedziach tutaj, możesz użyć Dir.glob. Należy pamiętać, że foldery mogą zawierać wiele dziwnych znaków, a globalne argumenty są wzorcami, więc niektóre postacie mają specjalne znaczenie. Jako taka, jest to niebezpieczne, aby zrobić coś jak następuje:

Dir.glob("#{folder}/**/*") 

Zamiast zrobić:

Dir.chdir(folder) { Dir.glob("**/*").map {|path| File.expand_path(path) } } 
0

Oto przykład, który łączy w sobie dynamiczny odkrycie katalogu projektu Rails z Dir.glob:

dir = Dir.glob(Rails.root.join('app', 'assets', 'stylesheets', '*')) 
+0

Próbowałem tego >> 'config.assets.paths << Rails.root.join (" app "," assets "," * ")', ale nadal nie można było zobaczyć podkatalogów i plików w folderze zasobów za pomocą 'Rails.application.config.assets.paths' – vipin8169

Powiązane problemy