Path: utzoo!attcan!uunet!tut.cis.ohio-state.edu!ucbvax!iwarp.intel.com!news From: merlyn@iwarp.intel.com (Randal Schwartz) Newsgroups: comp.lang.perl Subject: Almost ftw() (was Re: How about building in directory-tree-walking? like "ftw()") Summary: my hat goes into the ring Message-ID: <1990Mar24.223653.2329@iwarp.intel.com> Date: 24 Mar 90 22:36:53 GMT References: <39362@iuvax.cs.indiana.edu> <7514@jpl-devvax.JPL.NASA.GOV> Sender: news@iwarp.intel.com Reply-To: merlyn@iwarp.intel.com (Randal Schwartz) Distribution: comp Organization: Stonehenge; netaccess via Intel, Beaverton, Oregon, USA Lines: 80 In-Reply-To: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) In article <7514@jpl-devvax.JPL.NASA.GOV>, lwall@jpl-devvax (Larry Wall) writes: [ his version of a file tree walker ] Well, inspired by Larry's posting (yeah, it happens :-), and by the ftw() manpage, here's my version (somewhat tested...): ================================================== snip snip sub ftw { local($path, $fn) = @_; local(*CHILD); local($/) = "\000"; local($_); $CHILD = open(CHILD,'-|'); die "ftw: Cannot fork ($!)" unless defined $CHILD; unless ($CHILD) { # I am the child chdir $path || die "Cannot cd to $path ($!)"; &ftw'helper($path); exit 0; } # I am the parent while ($_ = ) { chop; do $fn($_); } close(CHILD); } sub ftw'helper { # expects to be cd'ed to $DIR local(*DIR); ($DIR) = @_; local($dev, $ino, $mode, $nlink) = stat('.'); local($_,$name); opendir(DIR,'.') || die "Cannot open $DIR ($!)"; local(@filenames) = sort readdir(DIR); closedir(DIR); if ($nlink == 2) { print grep(!/^\.\.?$/ && s#[^\000]+#$DIR/$&\000#, @filenames); } else { for (@filenames) { next if /^\.\.?$/; $name = "$DIR/$_"; print $name,"\000"; next unless -d $_ && -r _ && -x _; next if -l $_; # don't follow symlinks unless (chdir $_) { warn "Cannot chdir to $name ($!)"; next; } &ftw'helper($name); chdir '..'; } } } sub printit { print @_,"\n"; } for (@ARGV) { print "== $_ == \n"; &ftw($_,"printit"); } ================================================== snip snip This allows a separate process to do the scrambling around the directories, so that the pathnames are all clean by the time they hit the function. Yeah, I could add a "-depth" type switch, but this is just something I whipped up in 15 minutes. As soon as I start actually *using* the beasty, it'll probably grow all sortsa switches. @a=split(//,",rkeacrl hher PeJust anot");print splice(@a,@a*2/3,@a*2/3+1)while@a; -- /=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\ | on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III | | merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn | \=Cute Quote: "Welcome to Portland, Oregon, home of the California Raisins!"=/