Commit | Line | Data |
a0d0e21e |
1 | package File::Find; |
2 | require 5.000; |
3 | require Exporter; |
4 | |
5 | @ISA = qw(Exporter); |
6 | @EXPORT = qw(find finddepth); |
7 | |
8 | # Usage: |
9 | # use File::Find; |
10 | # |
11 | # find(\&wanted, '/foo','/bar'); |
12 | # |
13 | # sub wanted { ... } |
14 | # where wanted does whatever you want. $dir contains the |
15 | # current directory name, and $_ the current filename within |
16 | # that directory. $name contains "$dir/$_". You are cd'ed |
17 | # to $dir when the function is called. The function may |
18 | # set $prune to prune the tree. |
19 | # |
20 | # This library is primarily for find2perl, which, when fed |
21 | # |
22 | # find2perl / -name .nfs\* -mtime +7 -exec rm -f {} \; -o -fstype nfs -prune |
23 | # |
24 | # spits out something like this |
25 | # |
26 | # sub wanted { |
27 | # /^\.nfs.*$/ && |
28 | # (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) && |
29 | # int(-M _) > 7 && |
30 | # unlink($_) |
31 | # || |
32 | # ($nlink || (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_))) && |
33 | # $dev < 0 && |
34 | # ($prune = 1); |
35 | # } |
36 | # |
37 | # Set the variable $dont_use_nlink if you're using AFS, since AFS cheats. |
38 | |
39 | sub find { |
40 | my $wanted = shift; |
41 | chop($cwd = `pwd`); |
42 | foreach $topdir (@_) { |
43 | (($topdev,$topino,$topmode,$topnlink) = stat($topdir)) |
44 | || (warn("Can't stat $topdir: $!\n"), next); |
45 | if (-d _) { |
46 | if (chdir($topdir)) { |
47 | ($dir,$_) = ($topdir,'.'); |
48 | $name = $topdir; |
49 | &$wanted; |
50 | ($fixtopdir = $topdir) =~ s,/$,, ; |
51 | &finddir($wanted,$fixtopdir,$topnlink); |
52 | } |
53 | else { |
54 | warn "Can't cd to $topdir: $!\n"; |
55 | } |
56 | } |
57 | else { |
58 | unless (($dir,$_) = $topdir =~ m#^(.*/)(.*)$#) { |
59 | ($dir,$_) = ('.', $topdir); |
60 | } |
61 | $name = $topdir; |
62 | chdir $dir && &$wanted; |
63 | } |
64 | chdir $cwd; |
65 | } |
66 | } |
67 | |
68 | sub finddir { |
69 | local($wanted,$dir,$nlink) = @_; |
70 | local($dev,$ino,$mode,$subcount); |
71 | local($name); |
72 | |
73 | # Get the list of files in the current directory. |
74 | |
75 | opendir(DIR,'.') || (warn "Can't open $dir: $!\n", return); |
76 | local(@filenames) = readdir(DIR); |
77 | closedir(DIR); |
78 | |
79 | if ($nlink == 2 && !$dont_use_nlink) { # This dir has no subdirectories. |
80 | for (@filenames) { |
81 | next if $_ eq '.'; |
82 | next if $_ eq '..'; |
83 | $name = "$dir/$_"; |
84 | $nlink = 0; |
85 | &$wanted; |
86 | } |
87 | } |
88 | else { # This dir has subdirectories. |
89 | $subcount = $nlink - 2; |
90 | for (@filenames) { |
91 | next if $_ eq '.'; |
92 | next if $_ eq '..'; |
93 | $nlink = $prune = 0; |
94 | $name = "$dir/$_"; |
95 | &$wanted; |
96 | if ($subcount > 0 || $dont_use_nlink) { # Seen all the subdirs? |
97 | |
98 | # Get link count and check for directoriness. |
99 | |
100 | ($dev,$ino,$mode,$nlink) = lstat($_) unless $nlink; |
101 | |
102 | if (-d _) { |
103 | |
104 | # It really is a directory, so do it recursively. |
105 | |
106 | if (!$prune && chdir $_) { |
107 | &finddir($wanted,$name,$nlink); |
108 | chdir '..'; |
109 | } |
110 | --$subcount; |
111 | } |
112 | } |
113 | } |
114 | } |
115 | } |
116 | |
117 | # Usage: |
118 | # use File::Find; |
119 | # |
120 | # finddepth(\&wanted, '/foo','/bar'); |
121 | # |
122 | # sub wanted { ... } |
123 | # where wanted does whatever you want. $dir contains the |
124 | # current directory name, and $_ the current filename within |
125 | # that directory. $name contains "$dir/$_". You are cd'ed |
126 | # to $dir when the function is called. The function may |
127 | # set $prune to prune the tree. |
128 | # |
129 | # This library is primarily for find2perl, which, when fed |
130 | # |
131 | # find2perl / -name .nfs\* -mtime +7 -exec rm -f {} \; -o -fstype nfs -prune |
132 | # |
133 | # spits out something like this |
134 | # |
135 | # sub wanted { |
136 | # /^\.nfs.*$/ && |
137 | # (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) && |
138 | # int(-M _) > 7 && |
139 | # unlink($_) |
140 | # || |
141 | # ($nlink || (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_))) && |
142 | # $dev < 0 && |
143 | # ($prune = 1); |
144 | # } |
145 | |
146 | sub finddepth { |
147 | my $wanted = shift; |
148 | chop($cwd = `pwd`); |
149 | foreach $topdir (@_) { |
150 | (($topdev,$topino,$topmode,$topnlink) = stat($topdir)) |
151 | || (warn("Can't stat $topdir: $!\n"), next); |
152 | if (-d _) { |
153 | if (chdir($topdir)) { |
154 | ($fixtopdir = $topdir) =~ s,/$,, ; |
155 | &finddepthdir($wanted,$fixtopdir,$topnlink); |
156 | ($dir,$_) = ($fixtopdir,'.'); |
157 | $name = $fixtopdir; |
158 | &$wanted; |
159 | } |
160 | else { |
161 | warn "Can't cd to $topdir: $!\n"; |
162 | } |
163 | } |
164 | else { |
165 | unless (($dir,$_) = $topdir =~ m#^(.*/)(.*)$#) { |
166 | ($dir,$_) = ('.', $topdir); |
167 | } |
168 | chdir $dir && &$wanted; |
169 | } |
170 | chdir $cwd; |
171 | } |
172 | } |
173 | |
174 | sub finddepthdir { |
175 | my($wanted,$dir,$nlink) = @_; |
176 | my($dev,$ino,$mode,$subcount); |
177 | my($name); |
178 | |
179 | # Get the list of files in the current directory. |
180 | |
181 | opendir(DIR,'.') || warn "Can't open $dir: $!\n"; |
182 | my(@filenames) = readdir(DIR); |
183 | closedir(DIR); |
184 | |
185 | if ($nlink == 2) { # This dir has no subdirectories. |
186 | for (@filenames) { |
187 | next if $_ eq '.'; |
188 | next if $_ eq '..'; |
189 | $name = "$dir/$_"; |
190 | $nlink = 0; |
191 | &$wanted; |
192 | } |
193 | } |
194 | else { # This dir has subdirectories. |
195 | $subcount = $nlink - 2; |
196 | for (@filenames) { |
197 | next if $_ eq '.'; |
198 | next if $_ eq '..'; |
199 | $nlink = $prune = 0; |
200 | $name = "$dir/$_"; |
201 | if ($subcount > 0) { # Seen all the subdirs? |
202 | |
203 | # Get link count and check for directoriness. |
204 | |
205 | ($dev,$ino,$mode,$nlink) = lstat($_) unless $nlink; |
206 | |
207 | if (-d _) { |
208 | |
209 | # It really is a directory, so do it recursively. |
210 | |
211 | if (!$prune && chdir $_) { |
212 | &finddepthdir($wanted,$name,$nlink); |
213 | chdir '..'; |
214 | } |
215 | --$subcount; |
216 | } |
217 | } |
218 | &$wanted; |
219 | } |
220 | } |
221 | } |
222 | |
223 | 1; |
224 | |