2010-03-24 7 views
250

Comment écrire une boucle dans ruby ​​pour pouvoir exécuter un bloc de code sur chaque fichier? Je suis nouveau à ruby, et j'ai conclu que la façon de faire est de faire chaque boucle.
Le fichier ruby ​​sera exécuté à partir d'un répertoire différent du répertoire dans lequel je veux passer.Parcourir tous les fichiers d'un répertoire

J'ai essayé le Dir.foreach et je n'ai pas réussi à le faire fonctionner.

+2

Pouvez-vous spécifier ce qui s'est passé lorsque vous avez essayé de le faire fonctionner? Quel code exact avez-vous essayé (ou le morceau pertinent, si c'est long)? Quels messages d'erreur avez-vous obtenus? 'Dir.foreach' fonctionne pour parcourir le contenu d'un répertoire, donc quelque chose d'autre se passe beaucoup. – Telemachus

+3

Si vous ne voulez que des fichiers dans votre répertoire, n'oubliez pas de tester les fichiers lors de l'itération du contenu du répertoire: 'do_something_with (entrée) si File.file? (Entrée)' –

+3

Utilisez ''img/*. {Jpg, png, gif, jpeg} ''pour récupérer plusieurs extensions. –

Répondre

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

Vous pouvez aussi utiliser Dir # [] ou Dir # glob –

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

En plus de Dir.new ('/ my/dir'), il y a aussi Dir.entries ('/ my/dir') mais Dir.foreach() est un peu plus succinct. –

+4

@ Z.E.D. Aussi 'Dir.foreach' itére alors que' Dir.entries' construit la totalité du tableau en même temps. Donc, si le répertoire est immense, c'est moins un coup de mémoire. (Pas habituellement un gros problème, probablement, mais quand même ...) – Telemachus

391

Comme d'autres l'ont dit, Dir.foreach est une bonne option ici. Toutefois, notez que Dir.entries et Dir.foreach afficheront toujours . et .. (les répertoires actuel et parent). Vous ne voudrez généralement pas travailler sur eux, afin que vous puissiez faire quelque chose comme ceci:

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

Dir.foreach et Dir.entries montrent également tous les éléments du répertoire - cachés et non cachés semblables. C'est souvent ce que vous voulez, mais si ce n'est pas le cas, vous devez faire quelque chose pour ignorer les fichiers et répertoires cachés.

Alternativement, vous pouvez regarder dans Dir.glob qui fournit simplement les jokers:

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

Utilisez 'Dir.foreach' si le répertoire contient un très grand nombre de fichiers! – Tilo

+4

merci! Petit mod pour le rendre encore meilleur: 'next if File.directory? item' –

+0

@ mr.buttons Cela ne fera pas toujours la bonne chose. Parfois, les gens veulent travailler sur * des répertoires * ainsi que des fichiers. J'ai donné le code pour éviter les listes spéciales pour '.' ou '..' parce que les gens veulent presque toujours ignorer ces deux. – Telemachus

11

La bibliothèque find est conçu pour cette tâche spécifique: http://stdlib.rubyonrails.org/libdoc/find/rdoc/index.html

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

C'est un rubis norme bibliothèque, donc il devrait être disponible

+1

'File.find' descend récursivement aussi loin que possible, à partir de n'importe quel chemin que vous lui donnez. Je ne suis pas sûr que ce soit ce que veut le PO. – Telemachus

+0

Je ne semble pas avoir accès à cette méthode - Find.find? Dois-je télécharger une bibliothèque pour inclure cette fonctionnalité? –

+0

@ user470184: "Rechercher" est une bibliothèque ruby ​​standard et devrait être disponible avec l'installation ruby ​​par défaut. Cependant, vous devez "require 'find" avant de pouvoir l'utiliser. – Faisal

91

Ceci est ma méthode préférée pour être facile lire:

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

Et vous pouvez même l'étendre à travailler sur tous les fichiers subdirs:

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

Dir a la syntaxe aussi plus courte pour obtenir un tableau de tous les fichiers du répertoire:

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

Qu'est-ce qui empêche les répertoires d'être utilisés avec les itérations de' fname'? –

2

J'aime celui-ci, qui n'a pas été mentionné ci-dessus. L'avantage est que vous obtenez un objet Pathname à la place d'une chaîne, avec lequel vous pouvez faire des choses utiles et traverser plus loin.

Questions connexes