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)

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

  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

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

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

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:

On 21.09.2006 11:06, Newbie wrote:

startsWith?(aString) like method?
Like this?
next if /^./ =~ file

  1. 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

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: