home *** CD-ROM | disk | FTP | other *** search
- ## ftw.pl rev 4.0
-
- package ftw;
-
- # &ftw("path","function-name")
- # calls &function-name("path/file") for each name returned by the
- # equivalent of "find path -xdev -print"
-
- sub main'ftw {
- local($path, $fn) = @_;
-
- $fn =~ s/^([^']+)$/(caller)[$[]."'".$1/e;
- if (-d $path) {
- &helper($path);
- } elsif (-e $path) {
- do $fn("$path");
- }
- }
-
- sub helper {
- local($path) = @_;
-
- local($dev, $ino, $mode, $nlink) = stat($path);
- local($_,*DIR);
- opendir(DIR,$path) || die "Cannot open $DIR ($!)";
- local(@filenames) = sort grep(!/^\.\.?$/, readdir(DIR));
- closedir(DIR);
- $path = "" if $path eq "/"; # don't double the /!
-
- if ($nlink == 2) {
- for (@filenames) {
- do $fn("$path/$_");
- }
- } else {
- for (@filenames) {
- $_ = "$path/$_";
- do $fn("$_"); # cannot pass $_ as lvalue
- next unless ! -l $_ && -d _ && -r _ && -x _;
- next if $dev != (stat(_))[$[+0]; # "-xdev"
- &helper("$_"); # recurse if directory
- }
- }
- }
-
- package ftw_root;
-
- # &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 main'ftw_root {
- local($fn) = @_;
- $fn =~ s/^([^']+)$/(caller)[$[]."'".$1/e;
- local(@devlist) = ('/');
- local($_);
- while ($_ = shift @devlist) {
- &main'ftw($_,"root_helper");
- }
- }
-
- sub 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(@devlist,$file);
- }
- do $fn("$file"); # don't pass $file as an lvalue
- }
-
- 1;
-