From: Karl von Laudermann Date: 2005-05-13T23:05:29+09:00 Subject: Re: Go through directories recursively Robert Klemme wrote: > Robert Klemme wrote: > > > > require 'find' > > > > def edit_directory(dir) > > Find::find(dir) do |f| > > if /\.jsp$/i =~ f and File.file? f > > # do something with f > > end > > end > > end > > > > Kind regards > > > > robert > > PS: You can also do > > Dir["**/*.jsp"].each do |f| > if File.file? f > # do something with f > end > end Question: what if the operation you want to perform is to delete directories or files? From my understanding of Find#find, it yields directories breadth-firsh rather than depth first. So if you want to delete a directory yielded to your block, do you have to call Find#prune on it to avoid messing up the traversal? Likewise for Dir["**/*.jsp"]. Does this form first create an internal array of file names before yielding them, or does it yield each file as it inspects each directory? If the latter, does the traversal get messed up if you delete a file out from under it? I didn't know about either of the two above options, so the first time I needed to traverse directories recursively (to delete files, no less) I rolled my own solution, shown below. Until I know that either of the above options is safe for this, I will continue to use it. # Yields the name of each directory within the specified directory # recursively. Order is depth-first, to accommodate deleting files in the # yielded directory from within the block. Passed in directory is yielded last def each_dir(base, &block) Dir.entries(base).each do |n| unless (n == '.') || (n == '..') # Don't traverse . or .. n = File.join(base, n) unless base == '.' if File.directory?(n) each_dir(n, &block) yield n end end end yield base end