Directory and file listing

Discussion in 'Ruby' started by adam beazley, Dec 28, 2005.

  1. adam beazley

    adam beazley Guest

    Hello,

    I am trying to write my first ruby script to be used with Sketchup.
    Basically it is the first part of the script that I am having a problem
    with. So here is what i am trying to do:
    1: person imputs the directory path---ie c://program.../yada/
    2: ruby reads all image files in that directory and stores the file
    names in a string to be used later on.


    So I basically what the script to go into a directory and list all of
    the file names. Then I can use those file names to feed into the rest of
    my script.

    any help would be appreciated,
    thanks,
    Adam

    --
    Posted via http://www.ruby-forum.com/.
     
    adam beazley, Dec 28, 2005
    #1
    1. Advertising

  2. Am Donnerstag, den 29.12.2005, 07:07 +0900 schrieb adam beazley:
    > Hello,
    >
    > I am trying to write my first ruby script to be used with Sketchup.
    > Basically it is the first part of the script that I am having a problem
    > with. So here is what i am trying to do:
    > 1: person imputs the directory path---ie c://program.../yada/
    > 2: ruby reads all image files in that directory and stores the file
    > names in a string to be used later on.
    >


    Hi,

    img = Dir['*.jpg']

    returns all jpg-images in the current working directory as an array. So
    you can iterate over it like:

    img.each do |img|
    p img
    end

    Cheers
    detlef

    >
    > So I basically what the script to go into a directory and list all of
    > the file names. Then I can use those file names to feed into the rest of
    > my script.
    >
    > any help would be appreciated,
    > thanks,
    > Adam
    >
     
    Detlef Reichl, Dec 28, 2005
    #2
    1. Advertising

  3. adam beazley

    adam beazley Guest

    thanks for your reply, I believe i understand, however I dont know how
    to make C:\Program Files\@Last Software\SketchUp 5\Materials the current
    directory in the program. Or how to make an option where the user can
    type in, or browse to their own directory.

    But on the string answer of your question:
    img.each do |img|
    p img
    end

    Does that mean that p will be a variable that will hold all the image
    names?

    thanks

    --
    Posted via http://www.ruby-forum.com/.
     
    adam beazley, Dec 28, 2005
    #3
  4. adam beazley

    Mike Harris Guest

    adam beazley wrote:

    >thanks for your reply, I believe i understand, however I dont know how
    >to make C:\Program Files\@Last Software\SketchUp 5\Materials the current
    >directory in the program. Or how to make an option where the user can
    >type in, or browse to their own directory.
    >
    >But on the string answer of your question:
    >img.each do |img|
    > p img
    >end
    >
    >Does that mean that p will be a variable that will hold all the image
    >names?
    >
    >thanks
    >
    >
    >


    img = Dir['*.jpg'] sets img to an array of the image names. the p in the next piece of code just means "do something." That code iterates through the array of image names. instead of p img, you could say print img, etc.
     
    Mike Harris, Dec 28, 2005
    #4
  5. > thanks for your reply, I believe i understand, however I dont know how
    > to make C:\Program Files\@Last Software\SketchUp 5\Materials the current
    > directory in the program.

    Dir.chdir "c:/Program Files/..." - use Dir.pwd to see where you are.

    > Or how to make an option where the user can
    > type in, or browse to their own directory.

    For instance like this:
    dir=3Dgets # get user input from stdin
    Dir.chdir dir # move to specified directory
    img=3DDir["*.jpg"] #get array of all jpg files
    puts img # print the filenames, one per line

    > But on the string answer of your question:
    > img.each do |img|
    > p img
    > end
    >
    > Does that mean that p will be a variable that will hold all the image
    > names?


    Nope. 'p' is a print command. 'img' is the variable that holds the image na=
    mes.

    Have a look at the documentation and some programming guides (ex.
    http://www.ruby-doc.org/docs/ProgrammingRuby/) , and use irb for
    experimentation.


    Good luck.

    jf
     
    Johannes Friestad, Dec 28, 2005
    #5
  6. > > But on the string answer of your question:
    > > img.each do |img|
    > > p img
    > > end
    > >
    > > Does that mean that p will be a variable that will hold all the image
    > > names?


    BTW: The example may be slightly confusing, in using the same variable
    name for the array of all image filenames as for the string holding a
    single filename.
    It can be rewritten like this:

    images=3DDir["*.jpg"]
    images.each do |img|
    p img
    end

    Here, 'images' is an array (list/collection) of all image file names,
    'img' is a string holding a single filename.

    jf
     
    Johannes Friestad, Dec 28, 2005
    #6
  7. adam beazley

    adam beazley Guest

    Thanks for all of the post so far I really appreciate it.
    Well here is the code which I havent got to work just yet so any advice
    would be appreciated:

    #-----------------------------------------------------------------------------

    require 'sketchup.rb'

    #-----------------------------------------------------------------------------


    dir=gets
    Dir.chdir dir
    #Dir.chdir "c:/Program Files/@Last Software/Sketchup 5/Materials/"
    images=Dir["*.jpg"]
    images.each do |img|

    end

    def materialimporter
    model = Sketchup.active_model
    materials = model.materials

    if (img)
    # Adds a material to the "in-use" material pallet.
    m = materials.add "img"
    begin
    # Returns nil if not successful, path if successful.
    Should return a texture object
    m.texture=images
    rescue
    UI.messagebox $!.message
    end

    else
    UI.messagebox "Failure"
    end

    end




    if( not file_loaded?("massmaterialimporter.rb") )

    # This will add a separator to the menu, but only once
    add_separator_to_menu("Plugins")

    plugins_menu = UI.menu("Plugins")
    Materials_menu = plugins_menu.add_submenu("Mass Material Importer")

    Materials_menu.add_item("Import Materials") { materialimporter }


    end

    #-----------------------------------------------------------------------------
    file_loaded("massmaterialimporter.rb")




    Ass you can see this script is meant to be put into a program called
    sketchup. Im trying to make sketchup create a new texture for every jpg
    in the given directory. Im a little confused as to how to make the
    program go down the list of jpg's and make a new texture for each jpg
    and naming that texture the same name as the jpg.

    ie
    ruby reads c://program...../.../.../sample.jpg
    creates a texture and names it "sample"
    then goes to the next jpg and does the same thing

    anyway thanks everyone

    --
    Posted via http://www.ruby-forum.com/.
     
    adam beazley, Dec 29, 2005
    #7
  8. adam beazley

    adam beazley Guest

    Ok i think you lost me im still very new to ruby and programming in
    general. I have some experience with C lang but not extensive. So as of
    now this is where I am at with this program.

    this first snippet is working:

    #-----------------------------------------------------------------------------

    require 'sketchup.rb'

    #-----------------------------------------------------------------------------


    def getfilenames

    prompts = ["Directory Location"]
    values = []
    results = inputbox prompts, values, "dir"
    if (!results)
    #failure
    return
    else
    #success: you can extract values from the results array
    end

    directory = results.to_s
    Dir.chdir directory
    #Dir.chdir "C:\Program Files\@Last Software\SketchUp 5\Materials"
    images=Dir["*.jpg"]


    #at this point the script is working
    #the current directory is set to what the user imput!
    #also the "images" array has all of the .jpg files inside it.
    #-------------------------------------------------------------------------------

    --So thats all working fine and dandy, the images array has all of the
    names of the jpg files in it and i can make them print one per line.
    However the
    images.each do |img| is not working I get a syntax error so im not sure
    why thats not working.
    Now im trying to think about how to make this more object oriented
    because the way this program will have to work. Basically I need the
    file names of the images to be in some sort of order.
    The way it works in sketchup is that I have to first create a "material"
    and name this material so that it is added to the "in-use" browser. Then
    I add the jpg texture to the already named material with the correct
    jpg.
    So im trying to figure out how to do this with ruby, so that the
    material is named the same as the texture without the .jpg suffix.

    Im guessing this can be achieved with a while loop and maybe sorting the
    "images array(alphabetically or by incrimenting the ?
    what do you think?

    Here is the correct script for adding a material, then naming it and
    then adding a texture to it:
    -------------------------------------------------------------------------
    def addMaterial
    model = Sketchup.active_model
    materials = model.materials
    # Adds a material to the "in-use" material pallet.
    m = materials.add "Material Name"
    begin
    # Returns nil if not successful, path if successful. Should
    return a texture object
    m.texture="c:\\Program Files\\@Last Software\\SketchUp
    4\\Materials\\Carpet.jpg"
    rescue
    UI.messagebox $!.message
    end
    -------------------------------------------------------------------------
    So how can I automate this script to loop until every jpg in the
    directory has been added to the "in-use" material pallet and named the
    same as its texture file.

    Thanks for all of the help, I really appreciate it.
    Adam

    --
    Posted via http://www.ruby-forum.com/.
     
    adam beazley, Dec 29, 2005
    #8
  9. adam beazley

    Dan Kohn Guest

    I'm not familiar with sketchup, but I can at least show you how
    iterations through an array should look:

    dir=gets
    Dir.chdir dir
    images=Dir["*.jpg"]
    images.each do |img|
    material_importer( img)
    end

    def material_importer( img)
    m = Sketchup.new
    m.sample_name = img
    m.filename = img + ".jpg"
    m.save
    end


    In other words, pass each element of the array (img) to your method
    (material_importer) and then do something with it there. You shouldn't
    meed to access the full array (images) from the method.
     
    Dan Kohn, Dec 29, 2005
    #9
  10. adam beazley

    Dan Kohn Guest

    In line 4 here, the array is sorted and then the method is called on
    each element of the array.

    dir=gets
    Dir.chdir dir
    images=Dir["*.jpg"]
    images.sort.each do |img|
    material_importer( img)
    end

    def material_importer( img)
    model = Sketchup.active_model
    materials = model.materials
    # Adds a material to the "in-use" material pallet.
    m = materials.add img.to_s
    begin
    # Returns nil if not successful, path if successful. Should
    # return a texture object
    m.texture= img.to_s + ".jpg"
    rescue
    UI.messagebox $!.message
    end
    end
     
    Dan Kohn, Dec 29, 2005
    #10
  11. adam beazley

    adam beazley Guest

    just a little update before I leave for the day, I kept trying the:
    images.each do |img_name| but never could get it to work, however I
    found that [images].to_s changed the array to a string which i can now
    access each file by using image[0] or image[1], image[2] etc....

    So now what I am thinking is I can do a while loop and make the name of
    the material and the texture start with images[0] and incrament by one
    until they are all exhausted. I need to search and find out how to
    increment in ruby (++i)?

    thanks everyone
    again any coments or help would be apreciated

    --
    Posted via http://www.ruby-forum.com/.
     
    adam beazley, Dec 29, 2005
    #11
  12. On Dec 29, 2005, at 5:22 PM, adam beazley wrote:

    > So now what I am thinking is I can do a while loop and make the
    > name of
    > the material and the texture start with images[0] and incrament by one
    > until they are all exhausted. I need to search and find out how to
    > increment in ruby (++i)?


    I'm starting to pick up Ruby, and I learned through trial and error
    recently that I had to increment like this:

    value += 1

    The ++ operator didn't seem to be present, and it's not listed in
    Table 22.4, Ruby operators, of Programming Ruby, 2nd ed.

    Regards,
    Craig
     
    Craig Demyanovich, Dec 29, 2005
    #12
  13. On 12/29/05, adam beazley <> wrote:
    > Ok i think you lost me im still very new to ruby and programming in
    > general. I have some experience with C lang but not extensive. So as of
    > now this is where I am at with this program.
    >
    > this first snippet is working:
    >
    > <snip>
    >
    > #at this point the script is working
    > #the current directory is set to what the user imput!
    > #also the "images" array has all of the .jpg files inside it.
    > #------------------------------------------------------------------------=

    -------
    >
    > Here is the correct script for adding a material, then naming it and
    > then adding a texture to it:
    > -------------------------------------------------------------------------
    > def addMaterial
    > model =3D Sketchup.active_model
    > materials =3D model.materials
    > # Adds a material to the "in-use" material pallet.
    > m =3D materials.add "Material Name"
    > begin
    > # Returns nil if not successful, path if successful. Should
    > return a texture object
    > m.texture=3D"c:\\Program Files\\@Last Software\\SketchUp
    > 4\\Materials\\Carpet.jpg"
    > rescue
    > UI.messagebox $!.message
    > end
    > -------------------------------------------------------------------------
    > So how can I automate this script to loop until every jpg in the
    > directory has been added to the "in-use" material pallet and named the
    > same as its texture file.
    >


    addMaterial needs to take a parameter, so it can be used without
    knowing what context it's in. Also.. I'm not sure why you have
    begin/rescue/end in there. How could assigning a string to
    "m.texture" ever fail? If your texture=3D(texture_name) method in
    'materials' might raise an exception, you might want to consider
    handling it there, and having it return nil if no texture could be
    created.
    Anyway..

    def addMaterial(file_path)
    model =3D Sketchup.active_model
    materials =3D model.materials
    material_name =3D File.basename(file_path) # returns Carpet.jpg from
    c:/program files/etc/Carpet.jpg
    # Adds a material to the "in-use" material pallet.
    m =3D materials.add material_name # e.g. Carpet.jpg
    begin
    # Returns nil if not successful, path if successful. Should return
    a texture object
    m.texture =3D file_path
    rescue
    UI.messagebox $!.message
    end
    end

    Now you can do:
    images.each do |image_file|
    addMaterial(image_file)
    end

    The above is a 'block', and the "image_file" variable is only
    available between the 'do' and 'end' keywords.
    In your code, you were trying to access it from elsewhere, which isn't corr=
    ect.
    Your code comment:
    # Returns nil if not successful, path if successful. Should return a
    texture object
    ..doesn't make too much sense to me. You're setting the path, so why
    does it get returned?
    Also, if "UI.messagebox" has a return value, sometimes your
    addMaterial method won't behave as you expect. I think you should
    revisit the use of begin/rescue/end in this case.

    Further, you should put some thought into where addMaterial (in Ruby
    style, add_material) should live.
    If you put it in the same class as 'materials', you can avoid the
    first few lines, and skip straight to 'materials.add'

    Good luck,
    --Wilson.
     
    Wilson Bilkovich, Dec 29, 2005
    #13
  14. adam beazley

    adam beazley Guest

    thanks for your reply.

    Well I am almost there I just need a little more help to get me home.
    Here is the script so far, the trouble I am having now is with the while
    loop.
    --------------------------------------------

    def materialimporter

    prompt = ["Directory Location"]
    value = []
    results = inputbox prompt, value, "Directory"
    if (!results)
    #failure
    return
    else
    #success: you can extract values from the results array
    end

    directory = results.to_s
    Dir.chdir directory
    images=Dir["*.*"]
    [images].to_s

    maxnum = images.length
    img_num = 0
    model = Sketchup.active_model
    materials = model.materials

    while images <= maxnum

    m = materials.add "images[img_num]"
    m.texture=images[img_num]
    img_num += 1
    end
    end


    So the while loop doesnt seem to be working at all and im not sure why.
    Please help.
    thanks

    --
    Posted via http://www.ruby-forum.com/.
     
    adam beazley, Dec 30, 2005
    #14
  15. Change the 'while' to:

    while img_num <= maxnum

    then give it a try.
     
    Dale Martenson, Dec 30, 2005
    #15
  16. adam beazley

    adam beazley Guest

    Nevermind,
    I figured it out and the script works and it does exactly what I wanted
    it to do. Thank you so much everyone, I appreciate the support on this
    one. Here is the final code:


    #-----------------------------------------------------------------------------

    require 'sketchup.rb'

    #-----------------------------------------------------------------------------


    def materialimporter

    prompt = ["Directory Location"]
    value = []
    results = inputbox prompt, value, "Directory"
    if (!results)
    #failure
    return
    else
    #success: you can extract values from the results array
    end

    directory = results.to_s
    Dir.chdir directory
    images=Dir["*.*"]
    [images].to_s

    maxnum = images.length
    img_num = 0
    model = Sketchup.active_model
    materials = model.materials

    until img_num > maxnum

    m = materials.add images[img_num]
    m.texture=images[img_num]
    img_num += 1
    end
    end





    if( not file_loaded?("massmaterialimporter.rb") )

    # This will add a separator to the menu, but only once
    add_separator_to_menu("Plugins")

    plugins_menu = UI.menu("Plugins")

    plugins_menu.add_item("Import Materials") { materialimporter }

    end

    #-----------------------------------------------------------------------------
    file_loaded("massmaterialimporter.rb")




    So i only have one last question:
    I would like it if the name of the material could be brushedsteel
    instead of brushedsteel.jpg so how do I take off the file extension?

    thanks

    --
    Posted via http://www.ruby-forum.com/.
     
    adam beazley, Dec 30, 2005
    #16
  17. On 12/30/05, adam beazley <> wrote:
    > Nevermind,
    > I figured it out and the script works and it does exactly what I wanted
    > it to do. Thank you so much everyone, I appreciate the support on this
    > one. Here is the final code:
    >
    >
    > #------------------------------------------------------------------------=

    -----
    >
    > require 'sketchup.rb'
    >
    > #------------------------------------------------------------------------=

    -----
    >
    >
    > def materialimporter
    >
    > prompt =3D ["Directory Location"]
    > value =3D []
    > results =3D inputbox prompt, value, "Directory"
    > if (!results)
    > #failure
    > return
    > else
    > #success: you can extract values from the results array
    > end
    >
    > directory =3D results.to_s
    > Dir.chdir directory
    > images=3DDir["*.*"]
    > [images].to_s
    >
    > maxnum =3D images.length
    > img_num =3D 0
    > model =3D Sketchup.active_model
    > materials =3D model.materials
    >
    > until img_num > maxnum
    >
    > m =3D materials.add images[img_num]
    > m.texture=3Dimages[img_num]
    > img_num +=3D 1
    > end
    > end
    >
    >
    >
    >
    >
    > if( not file_loaded?("massmaterialimporter.rb") )
    >
    > # This will add a separator to the menu, but only once
    > add_separator_to_menu("Plugins")
    >
    > plugins_menu =3D UI.menu("Plugins")
    >
    > plugins_menu.add_item("Import Materials") { materialimporter }
    >
    > end
    >
    > #------------------------------------------------------------------------=

    -----
    > file_loaded("massmaterialimporter.rb")
    >
    >
    >
    >
    > So i only have one last question:
    > I would like it if the name of the material could be brushedsteel
    > instead of brushedsteel.jpg so how do I take off the file extension?
    >


    filename =3D 'example.jpg'
    name =3D File.basename(filename, '*.*')
    # name now has the value 'example'

    I'd also like to suggest that you read my last post more carefully..
    You're jumping through some unnecessary hoops with the 'images.to_s',
    and img_num things. 'each' does everything you need, all by itself.
     
    Wilson Bilkovich, Dec 30, 2005
    #17
    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. JD

    Directory Listing

    JD, Aug 24, 2003, in forum: Perl
    Replies:
    0
    Views:
    1,142
  2. Todd Lu

    Directory listing

    Todd Lu, Aug 31, 2004, in forum: ASP .Net
    Replies:
    2
    Views:
    472
    Todd Lu
    Aug 31, 2004
  3. Ferman
    Replies:
    4
    Views:
    497
    Roedy Green
    Aug 13, 2003
  4. ibic
    Replies:
    10
    Views:
    935
    Dave Thompson
    Nov 22, 2004
  5. Rajarshi Chakravarty

    directory listing without . and ..

    Rajarshi Chakravarty, Aug 23, 2010, in forum: Ruby
    Replies:
    7
    Views:
    154
    Suraj Kurapati
    Aug 23, 2010
Loading...

Share This Page