How to Traverse a Directory

Discussion in 'Ruby' started by Newbie, Sep 21, 2006.

  1. Newbie

    Newbie Guest

    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.)
    Newbie, Sep 21, 2006
    #1
    1. Advertising

  2. Newbie

    Marc Heiler Guest

    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/.
    Marc Heiler, Sep 21, 2006
    #2
    1. Advertising

  3. Newbie

    MonkeeSage Guest

    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, Sep 21, 2006
    #3
  4. Newbie

    MonkeeSage Guest

    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)
    MonkeeSage, Sep 21, 2006
    #4
  5. On 21.09.2006 11:06, Newbie wrote:
    > 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
    Robert Klemme, Sep 21, 2006
    #5
  6. Newbie

    Newbie Guest

    Thanks for all the help!

    MonkeeSage wrote:
    <stuff>
    Newbie, Sep 21, 2006
    #6
  7. Newbie

    Newbie Guest

    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 ;-)
    Newbie, Sep 21, 2006
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Thieum22
    Replies:
    1
    Views:
    681
    Joe Smith
    Aug 6, 2004
  2. Gary Wessle

    traverse directory with boost

    Gary Wessle, Aug 6, 2006, in forum: C++
    Replies:
    4
    Views:
    1,418
    Kai-Uwe Bux
    Aug 6, 2006
  3. jay
    Replies:
    0
    Views:
    130
  4. Traverse a directory

    , Jul 13, 2006, in forum: Perl Misc
    Replies:
    11
    Views:
    275
  5. glob and Traverse Directory

    , Jul 14, 2006, in forum: Perl Misc
    Replies:
    7
    Views:
    108
    Tad McClellan
    Jul 15, 2006
Loading...

Share This Page