perl 5.003_01: lib/dumpvar.pl
[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# }
8990e307 29#
30# Set the variable $dont_use_nlink if you're using AFS, since AFS cheats.
6e21c824 31
32sub find {
33 chop($cwd = `pwd`);
34 foreach $topdir (@_) {
35 (($topdev,$topino,$topmode,$topnlink) = stat($topdir))
36 || (warn("Can't stat $topdir: $!\n"), next);
37 if (-d _) {
38 if (chdir($topdir)) {
39 ($dir,$_) = ($topdir,'.');
40 $name = $topdir;
41 &wanted;
a0d0e21e 42 ($fixtopdir = $topdir) =~ s,/$,, ;
43 &finddir($fixtopdir,$topnlink);
6e21c824 44 }
45 else {
46 warn "Can't cd to $topdir: $!\n";
47 }
48 }
49 else {
50 unless (($dir,$_) = $topdir =~ m#^(.*/)(.*)$#) {
51 ($dir,$_) = ('.', $topdir);
52 }
8adcabd8 53 $name = $topdir;
6e21c824 54 chdir $dir && &wanted;
55 }
56 chdir $cwd;
57 }
58}
59
60sub finddir {
61 local($dir,$nlink) = @_;
62 local($dev,$ino,$mode,$subcount);
63 local($name);
64
65 # Get the list of files in the current directory.
66
8adcabd8 67 opendir(DIR,'.') || (warn "Can't open $dir: $!\n", return);
6e21c824 68 local(@filenames) = readdir(DIR);
69 closedir(DIR);
70
8990e307 71 if ($nlink == 2 && !$dont_use_nlink) { # This dir has no subdirectories.
6e21c824 72 for (@filenames) {
73 next if $_ eq '.';
74 next if $_ eq '..';
75 $name = "$dir/$_";
76 $nlink = 0;
77 &wanted;
78 }
79 }
80 else { # This dir has subdirectories.
81 $subcount = $nlink - 2;
82 for (@filenames) {
83 next if $_ eq '.';
84 next if $_ eq '..';
85 $nlink = $prune = 0;
86 $name = "$dir/$_";
87 &wanted;
8990e307 88 if ($subcount > 0 || $dont_use_nlink) { # Seen all the subdirs?
6e21c824 89
90 # Get link count and check for directoriness.
91
92 ($dev,$ino,$mode,$nlink) = lstat($_) unless $nlink;
93
94 if (-d _) {
95
96 # It really is a directory, so do it recursively.
97
98 if (!$prune && chdir $_) {
99 &finddir($name,$nlink);
100 chdir '..';
101 }
102 --$subcount;
103 }
104 }
105 }
106 }
107}
1081;