Path: utzoo!utgpu!news-server.csri.toronto.edu!clyde.concordia.ca!uunet!snorkelwacker!usc!elroy.jpl.nasa.gov!jpl-devvax!lwall From: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) Newsgroups: comp.lang.perl Subject: Re: How about building in directory-tree-walking? like "ftw()" Message-ID: <7514@jpl-devvax.JPL.NASA.GOV> Date: 23 Mar 90 01:16:38 GMT References: <39362@iuvax.cs.indiana.edu> Reply-To: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) Distribution: comp Organization: Jet Propulsion Laboratory, Pasadena, CA Lines: 55 In article <39362@iuvax.cs.indiana.edu> sahayman@iuvax.cs.indiana.edu (Steve Hayman) writes: : : How about perl having some sort of built-in directory tree walking? : (Or a perl library routine for this.) Something like the ftw() routine : that many versions of Unix have, that lets you walk through a directory : tree and call a specified function for each thing in the tree. : : I know I could open a pipe from "find ... -print" but I find it to be : a pain trying to deal with the different find options on different : machines. Some machines have -xdev, some have -mount, some have -prune : and so on. It would be great if perl had some sort of tree-walking : built in. Then I could make fancier selections than what 'find' lets me do. On the other hand, you can just mutate the following into what you want. This actually runs faster than find on my system, but that's because it's only looking at the names in leaf directories, not the inode. It also assumes that directory link counts work in the standard fashion. Larry #!/usr/local/bin/perl &dodir('.'); sub dodir { local($dir,$nlink) = @_; local($dev,$ino,$mode); ($dev,$ino,$mode,$nlink) = stat('.') unless $nlink; # first time opendir(DIR,'.') || die "Can't open $dir"; local(@filenames) = readdir(DIR); closedir(DIR); if ($nlink == 2) { # this dir has no subdirectories for (@filenames) { next if $_ eq '.'; next if $_ eq '..'; print "$dir/$_\n"; } } else { # this dir has subdirectories for (@filenames) { next if $_ eq '.'; next if $_ eq '..'; $name = "$dir/$_"; print $name,"\n"; ($dev,$ino,$mode,$nlink) = stat($_); next unless ($mode & 0170000) == 0040000; chdir $_ || die "Can't cd to $name"; &dodir($name,$nlink); chdir '..'; } } }