Newbie: need suggestion for "the ruby way"


#1

I write some code for generate file index for a directory.like this:
#!/usr/local/bin/ruby

def parse_options(args)
require ‘optparse’
require ‘ostruct’

options = OpenStruct.new
opts = OptionParser.new(“Usage: genindex [options] paths”)
options.dirs = []
opts.on_tail("-h", “–help”, “Show this message”) do
puts opts
exit
end
opts.on_tail("-v", “–version”, “Show version”) do
require ‘…/version’
puts Version.join(’.’)
exit
end
rest = opts.parse(args)
if rest.empty?:
puts opts
else
rest.each {|dir| options.dirs.push(Dir.new(File.expand_path(dir)))}
end
if $DEBUG
puts “get params:”
options.dirs.each {|dir| puts dir.path}
puts “end”
end
options
end

def get_indexs(curdir, indexs)
puts ‘indexing ‘, curdir.path if $DEBUG
curdir.each do |f|
next if [’.svn’, ‘.’, ‘…’].include?(f)
if File.directory?(File.join(curdir.path,f))
get_indexs(Dir.new(File.join(curdir.path,f)), indexs)
else
#it’s case insensitive
indexs[f.downcase] ||= []
indexs[f.downcase] += [File.join(curdir.path, f)]
end
end
end

def create_idx_file(options)
data_dir = File.join(File.dirname(File.expand_path(FILE)), ‘…’,
‘data’)
Dir.mkdir(data_dir) if not File.exist?(data_dir)
Dir.chdir(data_dir) do
options.dirs.each do |dir|
d = dir.path.split(File::SEPARATOR).join(’’)
next if Dir.foreach(’.’) do |idxdir|
next if [’.’, ‘…’, ‘.svn’].include?(idxdir)
#sub dir need be ingored but same dir need recreate
if d != idxdir and d.index(idxdir) == 0
puts "path #{File.join(d.split(’
’))} is ingored."
puts “Because it’s ancestors path
#{File.join(idxdir.split(’_’))} already been indexed.”
break true
end
end

  Dir.mkdir(d) if not File.exist?(d)
  Dir.chdir(d) do
    File.open('indexs.yaml', 'w') do |idx_file|
      require 'yaml'
      indexs = {}
      get_indexs(dir, indexs)
      YAML.dump(indexs, idx_file)
    end
  end
end

end
end

if $0 == FILE
begin
create_idx_file(parse_options(ARGV))
rescue Exception => e
puts e.to_s
end
end
and the test code is :
#!/usr/local/bin/ruby
$:.unshift(File.join(File.dirname(FILE),"…", “lib”))

require ‘test/unit’
require ‘genindex’
require ‘optparse’

class TextGenIndex < Test::Unit::TestCase
def test_option_parse
args = ["."]
assert_equal(File.expand_path("."),
parse_options(args).dirs[0].path)
args = [’…’]
assert_equal(File.expand_path("…"),
parse_options(args).dirs[0].path)
args = ["-sdf"]
assert_raise(OptionParser::InvalidOption) {parse_options(args)}
args = ["/var","/tmp"]
assert_equal("/var", parse_options(args).dirs[0].path)
assert_equal("/tmp", parse_options(args).dirs[1].path)
end
def test_create_idx_file
data_dir = File.join(File.dirname(File.expand_path(FILE)),
‘…’, ‘data’)
args = [’.’]
create_idx_file(parse_options(args))
assert_equal(File.exist?(data_dir), true)
index_dir = File.join(File.dirname(File.expand_path(FILE)),
‘…’, ‘data’, File.expand_path(’.’).split(File::SEPARATOR).join(’’))
assert_equal(File.exist?(index_dir), true)
args = [‘lib’, ‘test’]
create_idx_file(parse_options(args))
assert_equal(File.exist?(File.join(data_dir,
data_dir.split(File::SEPARATOR)[0…-4].push(‘lib’).join(’
’))), false)
require ‘yaml’
index_file = File.join(index_dir, ‘indexs.yaml’)
indexs = YAML.load(File.open(index_file))
assert_equal(indexs[‘version.rb’.downcase][0],
File.join(data_dir.split(File::SEPARATOR)[0…-4], ‘version.rb’))
end
end

I need some help for going to “the ruby way”.
this my first question on the group and I must apologize for my poor
english and thanks a lot for your suggestion for my ruby code or my
english.
So, any suggestion is wellcome.


#2

It might be more helpful to show what kind of output you want, rather
than what code you’ve created.

However, for a simple recursive directory listing, look more into the
Dir object:

depth = 1 #current or one directory down
files = Dir[’**/*’].reject {|item|
#filter out directories and directory depth
File.directory?(item) or File.dirname(item).split(’/’).size > depth
}
puts files

You can add more logic to filter out other files, organize them in a
tree-like structure, etc. But, the Dir object and methods are VERY
useful when used with File and other common Array and String methods.


#3

thanks a lot.
I just want to index the files and only files in some directory.
like this:
dir_a/dir_b/file_c
dir_a/file_d
will indexed as
file_c->dir_a/dir_b/file_c
file_d->dir_a/file_d
and dump this with YAML.

Now I think I can do that like this:
Dir.chdir(d) do
File.open(‘indexs.yaml’, ‘w’) do |idx_file|
require ‘yaml’
indexs = {}
Dir.chdir(dir.path) do
Dir[’**/*’].reject {|item| File.directory?(item)}
end
YAML.dump(indexs, idx_file)
end
end

so I do’t need the recursive procudure.


#4

yes, this is what i want.
thanks very much.


#5

2006/2/21, Joby B. removed_email_address@domain.invalid:

}
puts files

You can add more logic to filter out other files, organize them in a
tree-like structure, etc. But, the Dir object and methods are VERY
useful when used with File and other common Array and String methods.

Not that there is module Find which has recursion built in:

require ‘find’
Find.find(’.’) {|f| puts f}

Kind regards

robert