Hugh Sasse
12/16/2008 1:50:00 PM
On Tue, 16 Dec 2008, Brad Volz wrote:
> Hello,
>
> I seem to be having some difficulty creating a version of python's os.walk()
> for ruby, and I was hoping for some pointers.
>
> As some background, python's os.walk() [1] is a generator function. It is
You can have generators in Ruby
ri Generator
furnishes you with the details...
> passed the top of a directory tree and it returns the following for each
> subdirectory that it encounters:
> . the working directory
> . an Array of subdirectories
> . an Array of non-directory files
>
> Here is some truncated output for my use case:
>
> > > > import os
> > > > repo = '/usr/local/nfsen/profiles-data/live/lax1er1'
> > > > for root, dirs, files in os.walk(repo):
> ... if len(files) == 288:
> ... print root
> ...
> /usr/local/nfsen/profiles-data/live/lax1er1/2008/11/11
> ..
> /usr/local/nfsen/profiles-data/live/lax1er1/2008/12/13
>
> Essentially, when there are exactly 288 files in a subdirectory, I want to
> print or otherwise do something with the working directory.
OK.
>
> Here is my attempt at simply translating this library function to ruby:
>
> #! /usr/bin/env ruby
>
> require 'pp'
>
> dirs = [ '/usr/local/nfsen/profiles-data/live/lax1er1' ]
>
> def find_dirs(top)
> dirs = []
> nondirs = []
> Dir.entries(top).each do |f|
> next if f =~ /(\.$|\.\.$)/
or maybe
next if f =~ /^\.\.?$/
or
next if f =~ /^\.{1,2}$/
> full_path = [top, f].join('/')
full_path = File.join(tmp,f) # separator agnostic
> if File.directory?(full_path)
> dirs.push(full_path)
> else
> nondirs.push(full_path)
> end
> end
>
> yield top, dirs, nondirs
yielding to a proc with arity 3....
>
> dirs.each do |d|
> if File.directory?(d)
> for o in find_dirs(d) { |a,b,c| puts "#{a} #{b} #{c}"}
> yield o
yielding to a proc with arity 1
That may be one problem
> end
> end
> end
> end
>
> find_dirs(dirs[0]) do |top,dirs,nondirs|
> if nondirs.length == 288
> puts "#{top}"
> end
> end
>
> There are some things that I know are wrong or missing, but that is due to
> trying to get something to run at all without throwing an exception.
ri Find is short enough to quote:
------------------------------------------------------------ Class: Find
The +Find+ module supports the top-down traversal of a set of file
paths.
For example, to total the size of all files under your home
directory, ignoring anything in a "dot" directory (e.g.
$HOME/.ssh):
require 'find'
total_size = 0
Find.find(ENV["HOME"]) do |path|
if FileTest.directory?(path)
if File.basename(path)[0] == ?.
Find.prune # Don't look any further into this directory.
else
next
end
else
total_size += FileTest.size(path)
end
end
------------------------------------------------------------------------
Instance methods:
-----------------
find, prune
That will do most of the lifting for you...
[...]
Hugh