This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
mention "r" debugger command (from Ilya Zakharevich)
[perl5.git] / lib / File / Find.pm
CommitLineData
a0d0e21e 1package File::Find;
17f410f9 2use 5.005_64;
a0d0e21e 3require Exporter;
6280b799 4require Cwd;
a0d0e21e 5
f06db76b
AD
6=head1 NAME
7
8find - traverse a file tree
9
10finddepth - traverse a directory structure depth-first
11
12=head1 SYNOPSIS
13
14 use File::Find;
81793b90 15 find(\&wanted, '/foo', '/bar');
f06db76b 16 sub wanted { ... }
237437d0 17
f06db76b 18 use File::Find;
81793b90 19 finddepth(\&wanted, '/foo', '/bar');
f06db76b 20 sub wanted { ... }
81793b90
GS
21
22 use File::Find;
23 find({ wanted => \&process, follow => 1 }, '.');
f06db76b
AD
24
25=head1 DESCRIPTION
26
20408e3c 27The first argument to find() is either a hash reference describing the
81793b90 28operations to be performed for each file, or a code reference.
20408e3c 29
81793b90
GS
30Here are the possible keys for the hash:
31
32=over 3
33
34=item C<wanted>
35
36The value should be a code reference. This code reference is called
37I<the wanted() function> below.
38
39=item C<bydepth>
40
41Reports the name of a directory only AFTER all its entries
42have been reported. Entry point finddepth() is a shortcut for
43specifying C<{ bydepth => 1 }> in the first argument of find().
44
45=item C<follow>
46
47Causes symbolic links to be followed. Since directory trees with symbolic
48links (followed) may contain files more than once and may even have
49cycles, a hash has to be built up with an entry for each file.
50This might be expensive both in space and time for a large
51directory tree. See I<follow_fast> and I<follow_skip> below.
52If either I<follow> or I<follow_fast> is in effect:
53
54=over 6
55
a45bd81d 56=item *
81793b90
GS
57
58It is guarantueed that an I<lstat> has been called before the user's
59I<wanted()> function is called. This enables fast file checks involving S< _>.
60
a45bd81d 61=item *
81793b90
GS
62
63There is a variable C<$File::Find::fullname> which holds the absolute
64pathname of the file with all symbolic links resolved
65
66=back
67
68=item C<follow_fast>
69
70This is similar to I<follow> except that it may report some files
71more than once. It does detect cycles however.
72Since only symbolic links have to be hashed, this is
73much cheaper both in space and time.
74If processing a file more than once (by the user's I<wanted()> function)
75is worse than just taking time, the option I<follow> should be used.
76
77=item C<follow_skip>
78
79C<follow_skip==1>, which is the default, causes all files which are
80neither directories nor symbolic links to be ignored if they are about
81to be processed a second time. If a directory or a symbolic link
82are about to be processed a second time, File::Find dies.
83C<follow_skip==0> causes File::Find to die if any file is about to be
84processed a second time.
85C<follow_skip==2> causes File::Find to ignore any duplicate files and
86dirctories but to proceed normally otherwise.
20408e3c 87
f06db76b 88
81793b90
GS
89=item C<no_chdir>
90
91Does not C<chdir()> to each directory as it recurses. The wanted()
92function will need to be aware of this, of course. In this case,
93C<$_> will be the same as C<$File::Find::name>.
94
95=item C<untaint>
96
97If find is used in taint-mode (-T command line switch or if EUID != UID
98or if EGID != GID) then internally directory names have to be untainted
99before they can be cd'ed to. Therefore they are checked against a regular
100expression I<untaint_pattern>. Note, that all names passed to the
101user's I<wanted()> function are still tainted.
102
103=item C<untaint_pattern>
104
105See above. This should be set using the C<qr> quoting operator.
106The default is set to C<qr|^([-+@\w./]+)$|>.
107Note that the paranthesis which are vital.
108
109=item C<untaint_skip>
110
111If set, directories (subtrees) which fail the I<untaint_pattern>
112are skipped. The default is to 'die' in such a case.
113
114=back
115
116The wanted() function does whatever verifications you want.
117C<$File::Find::dir> contains the current directory name, and C<$_> the
118current filename within that directory. C<$File::Find::name> contains
119the complete pathname to the file. You are chdir()'d to C<$File::Find::dir> when
120the function is called, unless C<no_chdir> was specified.
121When <follow> or <follow_fast> are in effect there is also a
122C<$File::Find::fullname>.
123The function may set C<$File::Find::prune> to prune the tree
124unless C<bydepth> was specified.
e7b91b67
GS
125Unless C<follow> or C<follow_fast> is specified, for compatibility
126reasons (find.pl, find2perl) there are in addition the following globals
127available: C<$File::Find::topdir>, C<$File::Find::topdev>, C<$File::Find::topino>,
128C<$File::Find::topmode> and C<$File::Find::topnlink>.
47a735e8 129
20408e3c 130This library is useful for the C<find2perl> tool, which when fed,
f06db76b
AD
131
132 find2perl / -name .nfs\* -mtime +7 \
81793b90 133 -exec rm -f {} \; -o -fstype nfs -prune
f06db76b
AD
134
135produces something like:
136
137 sub wanted {
c7b9dd21 138 /^\.nfs.*\z/s &&
81793b90 139 (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_)) &&
f06db76b
AD
140 int(-M _) > 7 &&
141 unlink($_)
142 ||
81793b90 143 ($nlink || (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_))) &&
f06db76b 144 $dev < 0 &&
6280b799 145 ($File::Find::prune = 1);
f06db76b
AD
146 }
147
81793b90 148Set the variable C<$File::Find::dont_use_nlink> if you're using AFS,
6280b799 149since AFS cheats.
f06db76b 150
f06db76b
AD
151
152Here's another interesting wanted function. It will find all symlinks
153that don't resolve:
154
155 sub wanted {
81793b90 156 -l && !-e && print "bogus link: $File::Find::name\n";
237437d0 157 }
f06db76b 158
81793b90
GS
159See also the script C<pfind> on CPAN for a nice application of this
160module.
161
162=head1 CAVEAT
163
164Be aware that the option to follow symblic links can be dangerous.
165Depending on the structure of the directory tree (including symbolic
166links to directories) you might traverse a given (physical) directory
167more than once (only if C<follow_fast> is in effect).
168Furthermore, deleting or changing files in a symbolically linked directory
169might cause very unpleasant surprises, since you delete or change files
170in an unknown directory.
0530a6c4 171
0530a6c4 172
f06db76b
AD
173=cut
174
a0d0e21e 175@ISA = qw(Exporter);
6280b799
PP
176@EXPORT = qw(find finddepth);
177
a0d0e21e 178
81793b90
GS
179use strict;
180my $Is_VMS;
181
182require File::Basename;
183
184my %SLnkSeen;
185my ($wanted_callback, $avoid_nlink, $bydepth, $no_chdir, $follow,
186 $follow_skip, $full_check, $untaint, $untaint_skip, $untaint_pat);
187
188sub contract_name {
189 my ($cdir,$fn) = @_;
190
191 return substr($cdir,0,rindex($cdir,'/')) if $fn eq '.';
192
193 $cdir = substr($cdir,0,rindex($cdir,'/')+1);
194
195 $fn =~ s|^\./||;
196
197 my $abs_name= $cdir . $fn;
198
199 if (substr($fn,0,3) eq '../') {
200 do 1 while ($abs_name=~ s|/(?>[^/]+)/\.\./|/|);
201 }
202
203 return $abs_name;
204}
205
206
207sub PathCombine($$) {
208 my ($Base,$Name) = @_;
209 my $AbsName;
210
211 if (substr($Name,0,1) eq '/') {
212 $AbsName= $Name;
213 }
214 else {
215 $AbsName= contract_name($Base,$Name);
216 }
217
218 # (simple) check for recursion
219 my $newlen= length($AbsName);
220 if ($newlen <= length($Base)) {
221 if (($newlen == length($Base) || substr($Base,$newlen,1) eq '/')
222 && $AbsName eq substr($Base,0,$newlen))
223 {
224 return undef;
225 }
226 }
227 return $AbsName;
228}
229
230sub Follow_SymLink($) {
231 my ($AbsName) = @_;
232
233 my ($NewName,$DEV, $INO);
234 ($DEV, $INO)= lstat $AbsName;
235
236 while (-l _) {
237 if ($SLnkSeen{$DEV, $INO}++) {
238 if ($follow_skip < 2) {
239 die "$AbsName is encountered a second time";
a0d0e21e
LW
240 }
241 else {
81793b90 242 return undef;
a0d0e21e
LW
243 }
244 }
81793b90
GS
245 $NewName= PathCombine($AbsName, readlink($AbsName));
246 unless(defined $NewName) {
247 if ($follow_skip < 2) {
248 die "$AbsName is a recursive symbolic link";
249 }
250 else {
251 return undef;
a0d0e21e 252 }
81793b90
GS
253 }
254 else {
255 $AbsName= $NewName;
256 }
257 ($DEV, $INO) = lstat($AbsName);
258 return undef unless defined $DEV; # dangling symbolic link
259 }
260
261 if ($full_check && $SLnkSeen{$DEV, $INO}++) {
262 if ($follow_skip < 1) {
263 die "$AbsName encountered a second time";
264 }
265 else {
266 return undef;
267 }
268 }
269
270 return $AbsName;
271}
272
17f410f9 273our($dir, $name, $fullname, $prune);
81793b90
GS
274sub _find_dir_symlnk($$$);
275sub _find_dir($$$);
276
277sub _find_opt {
278 my $wanted = shift;
279 die "invalid top directory" unless defined $_[0];
280
281 my $cwd = $wanted->{bydepth} ? Cwd::fastcwd() : Cwd::cwd();
282 my $cwd_untainted = $cwd;
283 $wanted_callback = $wanted->{wanted};
284 $bydepth = $wanted->{bydepth};
285 $no_chdir = $wanted->{no_chdir};
286 $full_check = $wanted->{follow};
287 $follow = $full_check || $wanted->{follow_fast};
288 $follow_skip = $wanted->{follow_skip};
289 $untaint = $wanted->{untaint};
290 $untaint_pat = $wanted->{untaint_pattern};
291 $untaint_skip = $wanted->{untaint_skip};
292
e7b91b67
GS
293 # for compatability reasons (find.pl, find2perl)
294 our ($topdir, $topdev, $topino, $topmode, $topnlink);
81793b90
GS
295
296 # a symbolic link to a directory doesn't increase the link count
297 $avoid_nlink = $follow || $File::Find::dont_use_nlink;
298
299 if ( $untaint ) {
300 $cwd_untainted= $1 if $cwd_untainted =~ m|$untaint_pat|;
301 die "insecure cwd in find(depth)" unless defined($cwd_untainted);
302 }
303
e7b91b67 304 my ($abs_dir, $Is_Dir);
81793b90
GS
305
306 Proc_Top_Item:
307 foreach my $TOP (@_) {
308 my $top_item = $TOP;
c7b9dd21 309 $top_item =~ s|/\z|| unless $top_item eq '/';
81793b90
GS
310 $Is_Dir= 0;
311
3d1e7443
GS
312 ($topdev,$topino,$topmode,$topnlink) = stat $top_item;
313
81793b90
GS
314 if ($follow) {
315 if (substr($top_item,0,1) eq '/') {
316 $abs_dir = $top_item;
317 }
318 elsif ($top_item eq '.') {
319 $abs_dir = $cwd;
237437d0 320 }
81793b90
GS
321 else { # care about any ../
322 $abs_dir = contract_name("$cwd/",$top_item);
323 }
324 $abs_dir= Follow_SymLink($abs_dir);
325 unless (defined $abs_dir) {
326 warn "$top_item is a dangling symbolic link\n";
327 next Proc_Top_Item;
328 }
329 if (-d _) {
330 _find_dir_symlnk($wanted, $abs_dir, $top_item);
331 $Is_Dir= 1;
332 }
333 }
334 else { # no follow
e7b91b67 335 $topdir = $top_item;
e7b91b67 336 unless (defined $topnlink) {
81793b90
GS
337 warn "Can't stat $top_item: $!\n";
338 next Proc_Top_Item;
339 }
340 if (-d _) {
c7b9dd21 341 $top_item =~ s/\.dir\z// if $Is_VMS;
e7b91b67 342 _find_dir($wanted, $top_item, $topnlink);
81793b90
GS
343 $Is_Dir= 1;
344 }
237437d0 345 else {
81793b90
GS
346 $abs_dir= $top_item;
347 }
348 }
349
350 unless ($Is_Dir) {
351 unless (($_,$dir) = File::Basename::fileparse($abs_dir)) {
352 ($dir,$_) = ('.', $top_item);
353 }
354
355 $abs_dir = $dir;
356 if ($untaint) {
357 my $abs_dir_save = $abs_dir;
358 $abs_dir = $1 if $abs_dir =~ m|$untaint_pat|;
359 unless (defined $abs_dir) {
360 if ($untaint_skip == 0) {
361 die "directory $abs_dir_save is still tainted";
362 }
363 else {
364 next Proc_Top_Item;
365 }
366 }
367 }
368
369 unless ($no_chdir or chdir $abs_dir) {
370 warn "Couldn't chdir $abs_dir: $!\n";
371 next Proc_Top_Item;
372 }
373
374 $name = $abs_dir;
375
376 &$wanted_callback;
377
378 }
379
380 $no_chdir or chdir $cwd_untainted;
381 }
382}
383
384# API:
385# $wanted
386# $p_dir : "parent directory"
387# $nlink : what came back from the stat
388# preconditions:
389# chdir (if not no_chdir) to dir
390
391sub _find_dir($$$) {
392 my ($wanted, $p_dir, $nlink) = @_;
393 my ($CdLvl,$Level) = (0,0);
394 my @Stack;
395 my @filenames;
396 my ($subcount,$sub_nlink);
397 my $SE= [];
398 my $dir_name= $p_dir;
07867069 399 my $dir_pref= ( $p_dir eq '/' ? '/' : "$p_dir/" );
81793b90
GS
400 my $dir_rel= '.'; # directory name relative to current directory
401
402 local ($dir, $name, $prune, *DIR);
403
404 unless ($no_chdir or $p_dir eq '.') {
405 my $udir = $p_dir;
406 if ($untaint) {
407 $udir = $1 if $p_dir =~ m|$untaint_pat|;
408 unless (defined $udir) {
409 if ($untaint_skip == 0) {
410 die "directory $p_dir is still tainted";
411 }
412 else {
413 return;
414 }
237437d0 415 }
a0d0e21e 416 }
81793b90
GS
417 unless (chdir $udir) {
418 warn "Can't cd to $udir: $!\n";
419 return;
420 }
421 }
57e73c4b
GS
422
423 push @Stack,[$CdLvl,$p_dir,$dir_rel,-1] if $bydepth;
81793b90
GS
424
425 while (defined $SE) {
426 unless ($bydepth) {
427 $dir= $p_dir;
428 $name= $dir_name;
429 $_= ($no_chdir ? $dir_name : $dir_rel );
430 # prune may happen here
431 $prune= 0;
432 &$wanted_callback;
433 next if $prune;
434 }
435
436 # change to that directory
437 unless ($no_chdir or $dir_rel eq '.') {
438 my $udir= $dir_rel;
439 if ($untaint) {
440 $udir = $1 if $dir_rel =~ m|$untaint_pat|;
441 unless (defined $udir) {
442 if ($untaint_skip == 0) {
07867069
HJ
443 die "directory ("
444 . ($p_dir ne '/' ? $p_dir : '')
445 . "/) $dir_rel is still tainted";
81793b90
GS
446 }
447 }
448 }
449 unless (chdir $udir) {
07867069
HJ
450 warn "Can't cd to ("
451 . ($p_dir ne '/' ? $p_dir : '')
452 . "/) $udir : $!\n";
81793b90
GS
453 next;
454 }
455 $CdLvl++;
456 }
457
458 $dir= $dir_name;
459
460 # Get the list of files in the current directory.
461 unless (opendir DIR, ($no_chdir ? $dir_name : '.')) {
462 warn "Can't opendir($dir_name): $!\n";
463 next;
464 }
465 @filenames = readdir DIR;
466 closedir(DIR);
467
468 if ($nlink == 2 && !$avoid_nlink) {
469 # This dir has no subdirectories.
470 for my $FN (@filenames) {
c7b9dd21 471 next if $FN =~ /^\.{1,2}\z/;
81793b90 472
07867069 473 $name = $dir_pref . $FN;
81793b90
GS
474 $_ = ($no_chdir ? $name : $FN);
475 &$wanted_callback;
476 }
477
478 }
479 else {
480 # This dir has subdirectories.
481 $subcount = $nlink - 2;
482
483 for my $FN (@filenames) {
c7b9dd21 484 next if $FN =~ /^\.{1,2}\z/;
81793b90
GS
485 if ($subcount > 0 || $avoid_nlink) {
486 # Seen all the subdirs?
487 # check for directoriness.
488 # stat is faster for a file in the current directory
07867069 489 $sub_nlink = (lstat ($no_chdir ? $dir_pref . $FN : $FN))[3];
81793b90
GS
490
491 if (-d _) {
492 --$subcount;
c7b9dd21 493 $FN =~ s/\.dir\z// if $Is_VMS;
81793b90
GS
494 push @Stack,[$CdLvl,$dir_name,$FN,$sub_nlink];
495 }
496 else {
07867069 497 $name = $dir_pref . $FN;
81793b90
GS
498 $_= ($no_chdir ? $name : $FN);
499 &$wanted_callback;
500 }
501 }
07867069
HJ
502 else {
503 $name = $dir_pref . $FN;
81793b90
GS
504 $_= ($no_chdir ? $name : $FN);
505 &$wanted_callback;
506 }
507 }
508 }
17b275ff
RA
509 }
510 continue {
57e73c4b 511 while ( defined ($SE = pop @Stack) ) {
81793b90
GS
512 ($Level, $p_dir, $dir_rel, $nlink) = @$SE;
513 if ($CdLvl > $Level && !$no_chdir) {
f0963acb
GS
514 my $tmp = join('/',('..') x ($CdLvl-$Level));
515 die "Can't cd to $dir_name" . $tmp
516 unless chdir ($tmp);
81793b90
GS
517 $CdLvl = $Level;
518 }
07867069
HJ
519 $dir_name = ($p_dir eq '/' ? "/$dir_rel" : "$p_dir/$dir_rel");
520 $dir_pref = "$dir_name/";
57e73c4b
GS
521 if ( $nlink < 0 ) { # must be finddepth, report dirname now
522 $name = $dir_name;
523 $dir = $p_dir;
524 $_ = ($no_chdir ? $dir_name : $dir_rel );
525 &$wanted_callback;
526 } else {
527 push @Stack,[$CdLvl,$p_dir,$dir_rel,-1] if $bydepth;
528 last;
529 }
81793b90 530 }
a0d0e21e
LW
531 }
532}
533
81793b90
GS
534
535# API:
536# $wanted
537# $dir_loc : absolute location of a dir
538# $p_dir : "parent directory"
539# preconditions:
540# chdir (if not no_chdir) to dir
541
542sub _find_dir_symlnk($$$) {
543 my ($wanted, $dir_loc, $p_dir) = @_;
544 my @Stack;
545 my @filenames;
546 my $new_loc;
57e73c4b 547 my $pdir_loc = $dir_loc;
81793b90
GS
548 my $SE = [];
549 my $dir_name = $p_dir;
07867069
HJ
550 my $dir_pref = ( $p_dir eq '/' ? '/' : "$p_dir/" );
551 my $loc_pref = ( $dir_loc eq '/' ? '/' : "$dir_loc/" );
81793b90 552 my $dir_rel = '.'; # directory name relative to current directory
57e73c4b 553 my $byd_flag; # flag for pending stack entry if $bydepth
81793b90
GS
554
555 local ($dir, $name, $fullname, $prune, *DIR);
556
557 unless ($no_chdir or $p_dir eq '.') {
558 my $udir = $dir_loc;
559 if ($untaint) {
560 $udir = $1 if $dir_loc =~ m|$untaint_pat|;
561 unless (defined $udir) {
562 if ($untaint_skip == 0) {
563 die "directory $dir_loc is still tainted";
564 }
565 else {
566 return;
567 }
568 }
569 }
570 unless (chdir $udir) {
571 warn "Can't cd to $udir: $!\n";
572 return;
573 }
574 }
575
57e73c4b
GS
576 push @Stack,[$dir_loc,$pdir_loc,$p_dir,$dir_rel,-1] if $bydepth;
577
81793b90
GS
578 while (defined $SE) {
579
580 unless ($bydepth) {
581 $dir= $p_dir;
582 $name= $dir_name;
583 $_= ($no_chdir ? $dir_name : $dir_rel );
584 $fullname= $dir_loc;
585 # prune may happen here
586 $prune= 0;
587 &$wanted_callback;
588 next if $prune;
589 }
590
591 # change to that directory
592 unless ($no_chdir or $dir_rel eq '.') {
593 my $udir = $dir_loc;
594 if ($untaint) {
595 $udir = $1 if $dir_loc =~ m|$untaint_pat|;
596 unless (defined $udir ) {
597 if ($untaint_skip == 0) {
598 die "directory $dir_loc is still tainted";
a0d0e21e 599 }
237437d0 600 else {
81793b90 601 next;
237437d0 602 }
a0d0e21e
LW
603 }
604 }
81793b90
GS
605 unless (chdir $udir) {
606 warn "Can't cd to $udir: $!\n";
607 next;
608 }
609 }
610
611 $dir = $dir_name;
612
613 # Get the list of files in the current directory.
614 unless (opendir DIR, ($no_chdir ? $dir_loc : '.')) {
615 warn "Can't opendir($dir_loc): $!\n";
616 next;
617 }
618 @filenames = readdir DIR;
619 closedir(DIR);
620
621 for my $FN (@filenames) {
c7b9dd21 622 next if $FN =~ /^\.{1,2}\z/;
81793b90
GS
623
624 # follow symbolic links / do an lstat
07867069 625 $new_loc = Follow_SymLink($loc_pref.$FN);
81793b90
GS
626
627 # ignore if invalid symlink
628 next unless defined $new_loc;
629
630 if (-d _) {
57e73c4b 631 push @Stack,[$new_loc,$dir_loc,$dir_name,$FN,1];
81793b90
GS
632 }
633 else {
634 $fullname = $new_loc;
07867069 635 $name = $dir_pref . $FN;
81793b90
GS
636 $_ = ($no_chdir ? $name : $FN);
637 &$wanted_callback;
638 }
639 }
640
81793b90
GS
641 }
642 continue {
57e73c4b
GS
643 while (defined($SE = pop @Stack)) {
644 ($dir_loc, $pdir_loc, $p_dir, $dir_rel, $byd_flag) = @$SE;
07867069
HJ
645 $dir_name = ($p_dir eq '/' ? "/$dir_rel" : "$p_dir/$dir_rel");
646 $dir_pref = "$dir_name/";
647 $loc_pref = "$dir_loc/";
57e73c4b
GS
648 if ( $byd_flag < 0 ) { # must be finddepth, report dirname now
649 unless ($no_chdir or $dir_rel eq '.') {
650 my $udir = $pdir_loc;
651 if ($untaint) {
652 $udir = $1 if $dir_loc =~ m|$untaint_pat|;
653 }
654 unless (chdir $udir) {
655 warn "Can't cd to $udir: $!\n";
656 next;
657 }
658 }
659 $fullname = $dir_loc;
660 $name = $dir_name;
661 $dir = $p_dir;
662 $_ = ($no_chdir ? $dir_name : $dir_rel);
663 &$wanted_callback;
664 } else {
665 push @Stack,[$dir_loc, $pdir_loc, $p_dir, $dir_rel,-1] if $bydepth;
666 last;
667 }
a0d0e21e
LW
668 }
669 }
670}
671
81793b90 672
20408e3c 673sub wrap_wanted {
81793b90
GS
674 my $wanted = shift;
675 if ( ref($wanted) eq 'HASH' ) {
676 if ( $wanted->{follow} || $wanted->{follow_fast}) {
677 $wanted->{follow_skip} = 1 unless defined $wanted->{follow_skip};
678 }
679 if ( $wanted->{untaint} ) {
680 $wanted->{untaint_pattern} = qr|^([-+@\w./]+)$|
681 unless defined $wanted->{untaint_pattern};
682 $wanted->{untaint_skip} = 0 unless defined $wanted->{untaint_skip};
683 }
684 return $wanted;
685 }
686 else {
687 return { wanted => $wanted };
688 }
a0d0e21e
LW
689}
690
20408e3c 691sub find {
81793b90
GS
692 my $wanted = shift;
693 _find_opt(wrap_wanted($wanted), @_);
694 %SLnkSeen= (); # free memory
a0d0e21e
LW
695}
696
55d729e4 697sub finddepth {
81793b90
GS
698 my $wanted = wrap_wanted(shift);
699 $wanted->{bydepth} = 1;
700 _find_opt($wanted, @_);
701 %SLnkSeen= (); # free memory
20408e3c 702}
6280b799
PP
703
704# These are hard-coded for now, but may move to hint files.
10eba763 705if ($^O eq 'VMS') {
81793b90
GS
706 $Is_VMS = 1;
707 $File::Find::dont_use_nlink = 1;
748a9306
LW
708}
709
81793b90 710$File::Find::dont_use_nlink = 1
3e8584ad 711 if $^O eq 'os2' || $^O eq 'dos' || $^O eq 'amigaos' || $^O eq 'MSWin32';
6280b799 712
20408e3c
GS
713# Set dont_use_nlink in your hint file if your system's stat doesn't
714# report the number of links in a directory as an indication
715# of the number of files.
716# See, e.g. hints/machten.sh for MachTen 2.2.
81793b90
GS
717unless ($File::Find::dont_use_nlink) {
718 require Config;
719 $File::Find::dont_use_nlink = 1 if ($Config::Config{'dont_use_nlink'});
20408e3c
GS
720}
721
a0d0e21e 7221;