perl 4.0 patch 24: patch #20, continued
[p5sagit/p5-mst-13.2.git] / lib / find.pl
CommitLineData
6e21c824 1# Usage:
2# require "find.pl";
3#
4# &find('/foo','/bar');
5#
6# sub wanted { ... }
7# where wanted does whatever you want. $dir contains the
8# current directory name, and $_ the current filename within
9# that directory. $name contains "$dir/$_". You are cd'ed
10# to $dir when the function is called. The function may
11# set $prune to prune the tree.
12#
13# This library is primarily for find2perl, which, when fed
14#
15# find2perl / -name .nfs\* -mtime +7 -exec rm -f {} \; -o -fstype nfs -prune
16#
17# spits out something like this
18#
19# sub wanted {
20# /^\.nfs.*$/ &&
21# (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
22# int(-M _) > 7 &&
23# unlink($_)
24# ||
25# ($nlink || (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_))) &&
26# $dev < 0 &&
27# ($prune = 1);
28# }
29
30sub find {
31 chop($cwd = `pwd`);
32 foreach $topdir (@_) {
33 (($topdev,$topino,$topmode,$topnlink) = stat($topdir))
34 || (warn("Can't stat $topdir: $!\n"), next);
35 if (-d _) {
36 if (chdir($topdir)) {
37 ($dir,$_) = ($topdir,'.');
38 $name = $topdir;
39 &wanted;
40 $topdir =~ s,/$,, ;
41 &finddir($topdir,$topnlink);
42 }
43 else {
44 warn "Can't cd to $topdir: $!\n";
45 }
46 }
47 else {
48 unless (($dir,$_) = $topdir =~ m#^(.*/)(.*)$#) {
49 ($dir,$_) = ('.', $topdir);
50 }
51 chdir $dir && &wanted;
52 }
53 chdir $cwd;
54 }
55}
56
57sub finddir {
58 local($dir,$nlink) = @_;
59 local($dev,$ino,$mode,$subcount);
60 local($name);
61
62 # Get the list of files in the current directory.
63
64 opendir(DIR,'.') || warn "Can't open $dir: $!\n";
65 local(@filenames) = readdir(DIR);
66 closedir(DIR);
67
68 if ($nlink == 2) { # This dir has no subdirectories.
69 for (@filenames) {
70 next if $_ eq '.';
71 next if $_ eq '..';
72 $name = "$dir/$_";
73 $nlink = 0;
74 &wanted;
75 }
76 }
77 else { # This dir has subdirectories.
78 $subcount = $nlink - 2;
79 for (@filenames) {
80 next if $_ eq '.';
81 next if $_ eq '..';
82 $nlink = $prune = 0;
83 $name = "$dir/$_";
84 &wanted;
85 if ($subcount > 0) { # Seen all the subdirs?
86
87 # Get link count and check for directoriness.
88
89 ($dev,$ino,$mode,$nlink) = lstat($_) unless $nlink;
90
91 if (-d _) {
92
93 # It really is a directory, so do it recursively.
94
95 if (!$prune && chdir $_) {
96 &finddir($name,$nlink);
97 chdir '..';
98 }
99 --$subcount;
100 }
101 }
102 }
103 }
104}
1051;