#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2003
    Location
    Edinburgh, UK
    Posts
    84
    Rep Power
    11

    While not loop in ruby


    Hi All,

    I am trying to write a while not loop in Ruby, I have taken a look at all the docs etc on control structures but cant quite nail this one...

    Basically, I want to do something like this:

    Code:
    while Dir.entries("c:\\preprocess") != "." or ".."{
    Dir.foreach("c:\\preprocess") {|sitename|system("c:\\releasescripts\\aspincluder.exe c:\\preprocess #{sitename}")} 
    } end
    But I keep getting:
    DOS Code:
    C:/dir_test.rb:34: syntax error, unexpected '{', expecting kDO_COND or ':' or '\
    n' or ';'
    C:/dir_test.rb:36: syntax error, unexpected '}', expecting $end
    } end
     ^


    Can someone point out my error? I need the Dir.foreach to do something while the directory isnt "." or ".."

    Cheers
    -
    Karym6
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jan 2004
    Location
    Constant Limbo
    Posts
    989
    Rep Power
    363
    while Dir.entries("c:\\preprocess") != "." or ".."
    So you are aware, the logic of this statement is wrong, so the intended control is not actually what you would get.
    When you say:
    Code:
    while cond1 or cond2
    You are saying that either cond1 or cond2 evaluating to non nil/false will allow the loop to happen. So in your specific statement, you are saying
    Code:
    while X or ".."
    where X could be anything as ".." will always allow the loop to be entered.
    For example:
    Code:
    while ".." do
       puts "Still looping!"
    end
    will produce
    Code:
    Still looping!
    Still looping!
    Still looping!
    Still looping!
    Still looping!
    Still looping!
    Still looping!
    Still looping!
    Still looping!
    Still looping!
    Still looping!
    ...
    To answer your question directly, you could change the loop construct to use an iterator and only use items that qualify...
    Code:
    Dir.entries("c:\\preprocess").each do |entry|
       next if entry =~ /^\./
       # now any filename that begins with a '.' will not reach this line
    end
    That will eliminate 'hidden' files as well as simply '..' and '.', so you may have to adjust the reg ex to match against to suit your needs.
    True happiness is not getting what you want, it's wanting what you've already got.

    My Blog
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2003
    Location
    Edinburgh, UK
    Posts
    84
    Rep Power
    11
    Thanks for the reply L7Sqr!

    does this mean then, if I wished to exclude further directories that did not start with a "." I could use:

    Code:
    Dir.entries("c:\\preprocess").each do |entry|
       next if entry =~ /^\./ or "some_dir"
    end
    Or have I totally lost track?

    Cheers
    -
    K
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2007
    Location
    /usr/bin/ruby
    Posts
    63
    Rep Power
    28
    Code:
    next if entry =~ /^\./ or entry =~ /\.txt$/
    Will skip files beginning with a dot and ending in .txt, don't forget that the entry variable is each file name
    Last edited by [H4z3]; October 2nd, 2007 at 07:37 AM.
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2003
    Location
    Edinburgh, UK
    Posts
    84
    Rep Power
    11
    Originally Posted by [H4z3]
    Code:
    next if entry =~ /^\./ or entry =~ /\.txt$/
    Will skip files beginning with a dot and ending in .txt, don't forget that the entry variable is each file name
    ahh, I think I see now.

    So in order to ignore a whole directory as opposed to a file i can do:

    Code:
    next if entry =~ /^\./ or entry =~ /\some_dir$/
    cheers
    -
    K
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jan 2004
    Location
    Constant Limbo
    Posts
    989
    Rep Power
    363
    So in order to ignore a whole directory as opposed to a file i can do:
    The result of Dir.entries will be an array of strings. So there is no idea of file/directory at that point.
    If you have a list of items you would like to exclude, there is an easier method that you may be interested in.
    Code:
    # items to ignore
    ignored = ['.', '..', 'some_dir']
    (Dir.entries("c:\\preprocess") - ignored).each do |entry|
       # no items in ignored list will be present here
    end
    [edit]
    Also, if you are looking to only process files (and ignore all directories) then you can use test
    Code:
    Dir.entries("c:\\preprocess").each do |entry|
       next unless test ?f, entry
       # or, next if test ?d, entry
       # depends on what you want to limit
    end
    [/edit]

    Comments on this post

    • karym6 agrees : very helpful
    Last edited by L7Sqr; October 2nd, 2007 at 08:35 AM.
    True happiness is not getting what you want, it's wanting what you've already got.

    My Blog
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2003
    Location
    Edinburgh, UK
    Posts
    84
    Rep Power
    11
    Originally Posted by L7Sqr
    The result of Dir.entries will be an array of strings. So there is no idea of file/directory at that point.
    If you have a list of items you would like to exclude, there is an easier method that you may be interested in.
    Code:
    # items to ignore
    ignored = ['.', '..', 'some_dir']
    (Dir.entries("c:\\preprocess") - ignored).each do |entry|
       # no items in ignored list will be present here
    end
    [edit]
    Also, if you are looking to only process files (and ignore all directories) then you can use test
    Code:
    Dir.entries("c:\\preprocess").each do |entry|
       next unless test ?f, entry
       # or, next if test ?d, entry
       # depends on what you want to limit
    end
    [/edit]
    thanks very much L7Sqr this is what I didnt get from the docs etc
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2003
    Location
    Edinburgh, UK
    Posts
    84
    Rep Power
    11
    Originally Posted by karym6
    thanks very much L7Sqr this is what I didnt get from the docs etc
    one last question - would I be able to include specific directories with this code?

    Code:
    # items to ignore
    ignored = ['.', '..', 'some_dir']
    (Dir.entries("c:\\preprocess") - ignored).each do |entry|
       # no items in ignored list will be present here
    end
    is the - ignored the key part here?

    Cheers
    -
    Karim
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jan 2004
    Location
    Constant Limbo
    Posts
    989
    Rep Power
    363
    Yes. As I mentioned, the 'entries' method returns an array of strings.
    You are free to add (+) and remove (-) from as you see fit.
    As an example of adding and removing from an array:
    Code:
    a = ['a', 'b', 'c', 'd', 'e']
    b = ['d', 'e', 'f', 'g', 'h']
    a - b # produces ['a', 'b', 'c']
    a + b # produces ['a', 'b', 'c', 'd', 'e', 'd', 'e', 'f', 'g', 'h']
    Notice the duplicates in teh second result.
    True happiness is not getting what you want, it's wanting what you've already got.

    My Blog
  18. #10
  19. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2003
    Location
    Edinburgh, UK
    Posts
    84
    Rep Power
    11
    Originally Posted by L7Sqr
    Yes. As I mentioned, the 'entries' method returns an array of strings.
    You are free to add (+) and remove (-) from as you see fit.
    As an example of adding and removing from an array:
    Code:
    a = ['a', 'b', 'c', 'd', 'e']
    b = ['d', 'e', 'f', 'g', 'h']
    a - b # produces ['a', 'b', 'c']
    a + b # produces ['a', 'b', 'c', 'd', 'e', 'd', 'e', 'f', 'g', 'h']
    Notice the duplicates in teh second result.
    Excellent! Thankyou very much for your help so far

IMN logo majestic logo threadwatch logo seochat tools logo