2010-03-24 18 views
250

Wie schreibe ich eine Schleife in Ruby, so dass ich einen Code-Block für jede Datei ausführen kann?Iterieren durch jede Datei in einem Verzeichnis

Ich bin neu in Ruby, und ich habe festgestellt, dass die Art und Weise, dies zu tun ist ein jeder Schleife.
Die Ruby-Datei wird von einem anderen Verzeichnis ausgeführt als das Verzeichnis, das ich durchschleifen möchte.

Ich habe versucht, die Dir.foreach und ich konnte es nicht funktionieren.

+2

Können Sie angeben, was passiert ist, als Sie versucht haben, es zum Laufen zu bringen? Welchen genauen Code hast du probiert (oder den relevanten Teil, wenn er lang ist)? Welche Fehlermeldungen haben Sie erhalten? 'Dir.foreach' funktioniert, um über den Inhalt eines Verzeichnisses zu iterieren, also läuft noch etwas anderes. – Telemachus

+3

Wenn Sie nur Dateien in Ihrem Verzeichnis haben wollen, vergessen Sie nicht, beim Überschreiben des Verzeichnisinhalts nach Dateien zu suchen: 'do_something_with (entry) if File.file? (Entry)' –

+3

Verwenden Sie ''img/*. {Jpg, png, gif, jpeg}, um mehrere Erweiterungen zu erfassen. –

Antwort

22
Dir.foreach("/home/mydir") do |fname| 
    puts fname 
end 
+1

Alternativ verwenden Sie Dir # [] oder Dir # glob –

3
Dir.new('/my/dir').each do |name| 
    ... 
end 
+1

Zusätzlich zu Dir.new ('/ my/dir') gibt es auch Dir.entries ('/ my/dir'), aber Dir.foreach() ist ein bisschen prägnanter. –

+4

@ Z.E.D. Auch "Dir.foreach" iteriert, während "Dir.entries" das gesamte Array auf einmal aufbaut. Also, wenn das Verzeichnis immens ist, ist es weniger ein Speichertreffer. (Normalerweise keine große Sache, aber immer noch ...) – Telemachus

391

Wie andere gesagt haben, Dir.foreach ist eine gute Option hier. Beachten Sie jedoch, dass Dir.entries und Dir.foreach immer . und .. (das aktuelle und das übergeordnete Verzeichnis) anzeigen. Sie wollen in der Regel nicht an ihnen arbeiten, so können Sie etwas tun:

Dir.foreach('/path/to/dir') do |item| 
    next if item == '.' or item == '..' 
    # do work on real items 
end 

Dir.foreach und Dir.entries zeigen auch alle Elemente im Verzeichnis - versteckt und gleichermaßen nicht verborgen. Oft ist es das, was Sie wollen, aber wenn nicht, müssen Sie etwas tun, um die versteckten Dateien und Verzeichnisse zu überspringen.

Alternativ könnten Sie in Dir.glob aussehen soll, welche einfache Wildcard Matching bietet:

Dir.glob('/path/to/dir/*.rb') do |rb_file| 
    # do work on files ending in .rb in the desired directory 
end 
+11

Verwenden Sie "Dir.foreach", wenn das Verzeichnis eine große Anzahl von Dateien enthält! – Tilo

+4

danke! Kleiner Mod, um es noch besser zu machen: 'next if File.directory? item' –

+0

@ mr.buttons Das wird nicht immer das Richtige tun. Manchmal möchten Leute an * Verzeichnissen * sowie Dateien arbeiten. Ich habe Code gegeben, um die speziellen Einträge für '.' oder' ..' zu vermeiden, da die Leute diese beiden fast immer ignorieren wollen. – Telemachus

11

Der Fund Bibliothek für diese Aufgabe speziell entwickelt wurde: http://stdlib.rubyonrails.org/libdoc/find/rdoc/index.html

require 'find' 
Find.find(path) do |file| 
    # process 
end 

Dies ist ein Standard Rubin Bibliothek, so sollte es verfügbar sein

+1

'File.find' geht rekursiv so weit wie möglich, beginnend mit dem Pfad, den Sie ihm geben. Ich bin mir nicht sicher, dass das das OP will. – Telemachus

+0

Ich habe anscheinend keinen Zugang zu dieser Methode - Find.find? Muss ich eine Bibliothek herunterladen, um diese Funktionalität hinzuzufügen? –

+0

@ user470184: "Find" ist eine Standard-Ruby-Bibliothek und sollte mit der Standard-Ruby-Installation verfügbar sein. Sie müssen jedoch "finden" "bevor Sie es verwenden können". – Faisal

91

Dies ist meine Lieblingsmethode für einfach zu sein zu lesen:

Dir.glob("*/*.txt") do |my_text_file| 
    puts "working on: #{my_text_file}..." 
end 

Und Sie können dies sogar erweitern auf alle Dateien in subdirs arbeiten:

Dir.glob("**/*.txt") do |my_text_file| # note one extra "*" 
    puts "working on: #{my_text_file}..." 
end 
26

Dir auch kürzere Syntax ein Array aller Dateien aus dem Verzeichnis erhalten hat:

Dir['dir/to/files/*'].each do |fname| 
    # do something with fname 
end 
+0

Was in diesem Code verhindert, dass Verzeichnisse auch mit' fname's Iterationen verwendet werden? –

2

Ich mag diese, die oben nicht erwähnt wurde.

Der Vorteil ist, dass Sie ein Pfadnamen-Objekt anstelle einer Zeichenfolge erhalten, mit der Sie nützliche Dinge tun und weiter verfahren können.

Verwandte Themen