[RCR] Dir.recurse

I think it’d be useful (and worthwhile) to have a Dir.recurse method.
This method would take two optional arguments and a mandatory block. The
first argument, if given, is the directory to start recursing from. If
it is omitted, then recursion starts from the current directory. The
second argument, if given, specifies a maximum depth to recurse to. If
omitted, recursion would go as deep as possible.

The method would change to each directory under the current working
directory in turn, and also pass each directory’s name to the block. The
block would be executed once for each directory.

So, given a directory tree like
somedir
/
sub sub2
/
ssub ssub2

‘Dir.recurse("/somedir") { |x| puts x }’ would print:
/somedir
/somedir/sub
/somedir/sub/ssub
/somedir/sub/ssub2
/somedir/sub2

(though the order could differ, of course.)

Likewise, 'Dir.recurse("/somedir", 1) { puts Dir.pwd }'
would print:
/somedir
/somedir/sub
/somedir/sub2

i.e., only going one directory below the start directory.

Of course, in actual usage, you’d probably be more often interested in
the files in the directories than in the directories themselves.

Below is an example of how this could be implemented. I’m sure it needs
work, but I provide it just to give the general idea of what I am
talking about.

···

class Dir

def Dir.recurse(d=".", maxdepth=nil, &block)
raise ArgumentError unless block_given?
# If “maxdepth” is not specified, recurse as deeply as possible
if maxdepth
return 0 if maxdepth < 0
maxdepth -= 1
end
# Save working directory so it can be restored.
start = Dir.pwd
d = File.expand_path(d)
begin
Dir.chdir(d)
block.call(d)
Dir.entries(d).each do |f|
next unless (FileTest.directory? f) && (f !~ /^.{1,2}$/)
Dir.recurse(f, maxdepth, &block)
end
# Rescue “permission denied” errors, so that recurse continues and
# working directory is correctly restored.
rescue Errno::EACCES
$stderr.puts $!
end
Dir.chdir(start)
end
end

Hi Jim,

just a small proposal:

Jim Bob wrote:

begin
Dir.chdir(d)
block.call(d)
Dir.entries(d).each do |f|
next unless (FileTest.directory? f) && (f !~ /^.{1,2}$/)

→ next unless (FileTest.directory? f) && (f !~ /^..?$/)

  Dir.recurse(f, maxdepth, &block)
end

I don’t know why, but this way the pattern looks more readable to me :slight_smile:

Greets,

···


Volker Grabsch
—<<(())>>—
\frac{\left|\vartheta_0\times{\ell,\kappa\in\Re}\right|}{\sqrt
[G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint!c_\hbar\right]}}}

You might check out find (in the standard distribution) and find2
(available through the RAA), which seem to have some of the
functionality you are interested in.

Regards,

Mark

···

On Saturday, August 16, 2003, at 03:16 PM, Jim Bob wrote:

I think it’d be useful (and worthwhile) to have a Dir.recurse method.
This method would take two optional arguments and a mandatory block.
The
first argument, if given, is the directory to start recursing from. If
it is omitted, then recursion starts from the current directory. The
second argument, if given, specifies a maximum depth to recurse to. If
omitted, recursion would go as deep as possible.
[snip]

Did you see the “find” module? Should be able to do all this
even though the use of prune to limit max depth might not
be optimal for performance reasons.

Richard

···

On Sun, Aug 17, 2003 at 04:16:36AM +0900, Jim Bob wrote:

I think it’d be useful (and worthwhile) to have a Dir.recurse method.
This method would take two optional arguments and a mandatory block. The
first argument, if given, is the directory to start recursing from. If
it is omitted, then recursion starts from the current directory. The
second argument, if given, specifies a maximum depth to recurse to. If
omitted, recursion would go as deep as possible.

The method would change to each directory under the current working
directory in turn, and also pass each directory’s name to the block. The
block would be executed once for each directory.

So, given a directory tree like
somedir
/
sub sub2
/
ssub ssub2

‘Dir.recurse(“/somedir”) { |x| puts x }’ would print:
/somedir
/somedir/sub
/somedir/sub/ssub
/somedir/sub/ssub2
/somedir/sub2

[snip]

I totally agree. I’ve written one and use it in several scripts for
filesystem maintenance. Very handy! My version globbed the input first
(see Dir.glob), then proceeded to recurse into subdirectories making it
fairly equivalent to several command-line programs with their “recurse”
switch (e.g. chmod -R) but I think your version captures the necessary
functionality without the unnecessary frills. :slight_smile:

···

Jim Bob invalid@invalid.com wrote:

I think it’d be useful (and worthwhile) to have a Dir.recurse method.

Greg McIntyre ======[ greg@puyo.cjb.net ]===[ http://puyo.cjb.net ]===

Indeed it does. I wasn’t aware of that module, so thanks to you and
Richard for pointing it out.

···

In article 622D8E09-D115-11D7-BA1A-000393876156@cox.net, Mark Wilson wrote:

You might check out find (in the standard distribution) and find2
(available through the RAA), which seem to have some of the
functionality you are interested in.

Regards,

Mark