How to Traverse a Directory

def traverse(root)
   Dir.foreach(root) do |file|
     next if file[0] == ?.
     puts file
     traverse(root + '\\' + file) if File.directory?(root + '\\' + file)
   end
end

This is my initial attempt. Two things feel rather wrong:
1) Is there a simpler way to test the beginning of a string? A startsWith?(aString) like method?
2) I'm iterating through filenames, then appending the path each time. Is there a way to get a collection of File objects from a directory?

Any other pointers to where I could improve would also be greatly appreciated.

(I tried posting this twice through Teranews, but it doesn't seem to have got through.)

Cant really help you but just want to say that
next if file[0] == ?.

is something I did too to get rid of the . and .. which
dont really give me helpful info (when i look for real
files or directories for example)

···

--
Posted via http://www.ruby-forum.com/.

This should give you back the entries in a path (dir), so just call it
recursely:

<pre>
  def get_entries(path)
    dir_entries = nil
    begin
      Dir.chdir(path) do # get entries in this directory
        dir_entries = Dir.entries(path)
      end
    rescue SystemCallError
      @flash[:notice] = "No such path!"
      redirect_to :controller => 'explorer', :action => 'index'
    end
    dir_entries unless dir_entries == nil
  end
</pre>

try looking also here: http://gotapi.com/index.html

···

--
Igor MILOVANOVIĆ
http://f13o.pletisan.rs.ba/blog/

Newbie wrote:

def traverse(root)
   Dir.foreach(root) do |file|

You can use Dir #, #glob, or #entries also. If you use a glob or the
entries method, you can also automatically skip the . and .. --
Dir.entries(root)[2..-1] will give you an array of all the files and
subdirs in root, minus the first two (which are always . and ..) If you
do that, you can skip the next line.

Check out the docs to see how to use them further:
http://ruby-doc.org/core/classes/Dir.html

     next if file[0] == ?.

This will probably work for most cases in windows (though not always),
but it definitely a bad idea for any other OS (because filenames can
start with a . to mean they should be hidden in normal listing modes).
What I usually use is -- next if ['.', '..'].include? file -- which
checks if the full filename == '.' or '..'

     puts file
     traverse(root + '\\' + file) if File.directory?(root + '\\' + file)

This is also not very portable. Better to use File.join(root, file)

   end
end

Ps. Your directory traverser looks ALOT better than my first one did!

HTH,
Jordan

def traverse(root)
  Dir.foreach(root) do |file|
    next if file[0] == ?.
    puts file
    traverse(root + '\\' + file) if File.directory?(root + '\\' + file)
  end
end

This is my initial attempt. Two things feel rather wrong:
1) Is there a simpler way to test the beginning of a string? A startsWith?(aString) like method?

Like this?
next if /^\./ =~ file

2) I'm iterating through filenames, then appending the path each time. Is there a way to get a collection of File objects from a directory?

File objects are for actually reading and writing objects. You can do Dir["*"] which returns an array of strings.

Any other pointers to where I could improve would also be greatly appreciated.

Use Find:

irb(main):001:0> require 'find'
=> true
irb(main):002:0> Find.find('.') {|f| puts f}
.
./x
./prj-jar.txt
./jdk-jar.txt
=> nil

irb(main):005:0> Find.find('/tmp') {|f| puts f}
/tmp
/tmp/x
/tmp/prj-jar.txt
/tmp/jdk-jar.txt
=> nil

irb(main):008:0> Find.find '/tmp' do |f|
irb(main):009:1* next if File.directory? f
irb(main):010:1> puts f
irb(main):011:1> end
/tmp/x
/tmp/prj-jar.txt
/tmp/jdk-jar.txt

Note, you can also use File.join to portably combine paths.

Kind regards

  robert

···

On 21.09.2006 11:06, Newbie wrote:

MonkeeSage wrote:

> puts file
> traverse(root + '\\' + file) if File.directory?(root + '\\' + file)

This is also not very portable. Better to use File.join(root, file)

You can also refactor that to this:

puts file = File.join(root, file) # assignment returns its value
traverse(file) if File.directory?(file)

Thanks for all the help!

MonkeeSage wrote:
<stuff>

MonkeeSage wrote:

next if file[0] == ?.

This will probably work for most cases in windows (though not always),
but it definitely a bad idea for any other OS (because filenames can
start with a . to mean they should be hidden in normal listing modes).
What I usually use is -- next if ['.', '..'].include? file -- which
checks if the full filename == '.' or '..'

Good point - perhaps http://www.ruby-doc.org/core/classes/Find.html should be fixed :wink: