home *** CD-ROM | disk | FTP | other *** search
- ## ftw.pl rev 3.0
-
- # &ftw("path","function-name")
- # calls &function-name("path/file") for each name returned by the
- # equivalent of "find path -xdev -print"
-
- sub ftw {
- local($path, $fn) = @_;
- local(*CHILD);
- local($preslash) = $/;
- local($/);
- local($_);
- # flushing STDOUT:
- local($preselect) = select(STDOUT);
- local($prepipe) = $|;
- $| = 1;
- print "";
- $| = $prepipe;
- select($preselect);
- # end flushing STDOUT
- $CHILD = open(CHILD,'-|');
- die "ftw: Cannot fork ($!)" unless defined $CHILD;
- unless ($CHILD) { # I am the child
- $| = 1; # don't buffer stdout
- chdir $path || die "Cannot cd to $path ($!)";
- &ftw'helper($path);
- exit 0;
- }
- # I am the parent
- $/ = "\000";
- while (<CHILD>) {
- chop;
- {
- local($/) = $preslash;
- do $fn("".$_);
- }
- }
- close(CHILD);
- }
-
- sub ftw'helper {
- # expects to be cd'ed to $DIR
- local(*DIR); ($DIR) = @_;
- $DIR = "" if $DIR eq "/"; # no "//..."!
- 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 ! -l $_ && -d _ && -r _ && -x _;
- next if $dev != (stat(_))[$[+0]; # "-xdev"
- unless (chdir $_) {
- warn "Cannot chdir to $name ($!)";
- next;
- }
- &ftw'helper($name);
- chdir '..';
- }
- }
- }
-
- # &ftw_root("function-name")
- # calls &function-name("/file",stat("/file")) for each name
- # returned by the equivalent of "find / -fstype nfs -prune -o -print"
- # note that stat buffer _ is correct during the call (unlike &ftw() above)
-
- sub ftw_root {
- local($ftw_root'fn) = @_;
- local(@ftw_root'devlist) = ('/');
- local($_);
- while ($_ = shift @ftw_root'devlist) {
- &ftw($_,"ftw_root'helper");
- }
- }
-
- sub ftw_root'helper {
- local($file) = @_;
- local(@s) = lstat($file);
- return unless @s;
- local($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
- $atime,$mtime,$ctime,$blksize,$blocks) = @s;
- if (($ino == 2) && ($dev > 0) && ($dev < 16384)) {
- push(@ftw_root'devlist,$file);
- }
- do $ftw_root'fn("".$file);
- }
-
- 1;
-