5 use warnings::register;
12 find - traverse a file tree
14 finddepth - traverse a directory structure depth-first
19 find(\&wanted, '/foo', '/bar');
23 finddepth(\&wanted, '/foo', '/bar');
27 find({ wanted => \&process, follow => 1 }, '.');
31 The first argument to find() is either a hash reference describing the
32 operations to be performed for each file, or a code reference.
34 Here are the possible keys for the hash:
40 The value should be a code reference. This code reference is called
41 I<the wanted() function> below.
45 Reports the name of a directory only AFTER all its entries
46 have been reported. Entry point finddepth() is a shortcut for
47 specifying C<{ bydepth => 1 }> in the first argument of find().
51 The value should be a code reference. This code reference is used to
52 preprocess the current directory. The name of currently processed
53 directory is in $File::Find::dir. Your preprocessing function is
54 called after readdir() but before the loop that calls the wanted()
55 function. It is called with a list of strings (actually file/directory
56 names) and is expected to return a list of strings. The code can be
57 used to sort the file/directory names alphabetically, numerically,
58 or to filter out directory entries based on their name alone. When
59 I<follow> or I<follow_fast> are in effect, C<preprocess> is a no-op.
63 The value should be a code reference. It is invoked just before leaving
64 the currently processed directory. It is called in void context with no
65 arguments. The name of the current directory is in $File::Find::dir. This
66 hook is handy for summarizing a directory, such as calculating its disk
67 usage. When I<follow> or I<follow_fast> are in effect, C<postprocess> is a
72 Causes symbolic links to be followed. Since directory trees with symbolic
73 links (followed) may contain files more than once and may even have
74 cycles, a hash has to be built up with an entry for each file.
75 This might be expensive both in space and time for a large
76 directory tree. See I<follow_fast> and I<follow_skip> below.
77 If either I<follow> or I<follow_fast> is in effect:
83 It is guaranteed that an I<lstat> has been called before the user's
84 I<wanted()> function is called. This enables fast file checks involving S< _>.
88 There is a variable C<$File::Find::fullname> which holds the absolute
89 pathname of the file with all symbolic links resolved
95 This is similar to I<follow> except that it may report some files more
96 than once. It does detect cycles, however. Since only symbolic links
97 have to be hashed, this is much cheaper both in space and time. If
98 processing a file more than once (by the user's I<wanted()> function)
99 is worse than just taking time, the option I<follow> should be used.
103 C<follow_skip==1>, which is the default, causes all files which are
104 neither directories nor symbolic links to be ignored if they are about
105 to be processed a second time. If a directory or a symbolic link
106 are about to be processed a second time, File::Find dies.
107 C<follow_skip==0> causes File::Find to die if any file is about to be
108 processed a second time.
109 C<follow_skip==2> causes File::Find to ignore any duplicate files and
110 directories but to proceed normally otherwise.
112 =item C<dangling_symlinks>
114 If true and a code reference, will be called with the symbolic link
115 name and the directory it lives in as arguments. Otherwise, if true
116 and warnings are on, warning "symbolic_link_name is a dangling
117 symbolic link\n" will be issued. If false, the dangling symbolic link
118 will be silently ignored.
122 Does not C<chdir()> to each directory as it recurses. The wanted()
123 function will need to be aware of this, of course. In this case,
124 C<$_> will be the same as C<$File::Find::name>.
128 If find is used in taint-mode (-T command line switch or if EUID != UID
129 or if EGID != GID) then internally directory names have to be untainted
130 before they can be chdir'ed to. Therefore they are checked against a regular
131 expression I<untaint_pattern>. Note that all names passed to the user's
132 I<wanted()> function are still tainted. If this option is used while
133 not in taint-mode, C<untaint> is a no-op.
135 =item C<untaint_pattern>
137 See above. This should be set using the C<qr> quoting operator.
138 The default is set to C<qr|^([-+@\w./]+)$|>.
139 Note that the parentheses are vital.
141 =item C<untaint_skip>
143 If set, a directory which fails the I<untaint_pattern> is skipped,
144 including all its sub-directories. The default is to 'die' in such a case.
148 The wanted() function does whatever verifications you want.
149 C<$File::Find::dir> contains the current directory name, and C<$_> the
150 current filename within that directory. C<$File::Find::name> contains
151 the complete pathname to the file. You are chdir()'d to
152 C<$File::Find::dir> when the function is called, unless C<no_chdir>
153 was specified. When C<follow> or C<follow_fast> are in effect, there is
154 also a C<$File::Find::fullname>. The function may set
155 C<$File::Find::prune> to prune the tree unless C<bydepth> was
156 specified. Unless C<follow> or C<follow_fast> is specified, for
157 compatibility reasons (find.pl, find2perl) there are in addition the
158 following globals available: C<$File::Find::topdir>,
159 C<$File::Find::topdev>, C<$File::Find::topino>,
160 C<$File::Find::topmode> and C<$File::Find::topnlink>.
162 This library is useful for the C<find2perl> tool, which when fed,
164 find2perl / -name .nfs\* -mtime +7 \
165 -exec rm -f {} \; -o -fstype nfs -prune
167 produces something like:
171 (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_)) &&
175 ($nlink || (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_))) &&
177 ($File::Find::prune = 1);
180 Notice the C<_> in the above C<int(-M _)>: the C<_> is a magical
181 filehandle that caches the information from the preceding
182 stat(), lstat(), or filetest.
184 Here's another interesting wanted function. It will find all symbolic
185 links that don't resolve:
188 -l && !-e && print "bogus link: $File::Find::name\n";
191 See also the script C<pfind> on CPAN for a nice application of this
196 If you run your program with the C<-w> switch, or if you use the
197 C<warnings> pragma, File::Find will report warnings for several weird
198 situations. You can disable these warnings by putting the statement
200 no warnings 'File::Find';
202 in the appropriate scope. See L<perllexwarn> for more info about lexical
209 =item $dont_use_nlink
211 You can set the variable C<$File::Find::dont_use_nlink> to 1, if you want to
212 force File::Find to always stat directories. This was used for systems
213 that do not have the correct C<nlink> count for directories. Examples are
214 ISO-9660 (CD-R), AFS, and operating systems like OS/2, DOS and a couple of
217 Since now File::Find should now detect such things on-the-fly and switch it
218 self to using stat, this will probably not a problem to you.
220 If you do set $dont_use_nlink to 1, you will notice slow-downs.
224 Be aware that the option to follow symbolic links can be dangerous.
225 Depending on the structure of the directory tree (including symbolic
226 links to directories) you might traverse a given (physical) directory
227 more than once (only if C<follow_fast> is in effect).
228 Furthermore, deleting or changing files in a symbolically linked directory
229 might cause very unpleasant surprises, since you delete or change files
230 in an unknown directory.
240 Mac OS (Classic) users should note a few differences:
246 The path separator is ':', not '/', and the current directory is denoted
247 as ':', not '.'. You should be careful about specifying relative pathnames.
248 While a full path always begins with a volume name, a relative pathname
249 should always begin with a ':'. If specifying a volume name only, a
250 trailing ':' is required.
254 C<$File::Find::dir> is guaranteed to end with a ':'. If C<$_>
255 contains the name of a directory, that name may or may not end with a
256 ':'. Likewise, C<$File::Find::name>, which contains the complete
257 pathname to that directory, and C<$File::Find::fullname>, which holds
258 the absolute pathname of that directory with all symbolic links resolved,
259 may or may not end with a ':'.
263 The default C<untaint_pattern> (see above) on Mac OS is set to
264 C<qr|^(.+)$|>. Note that the parentheses are vital.
268 The invisible system file "Icon\015" is ignored. While this file may
269 appear in every directory, there are some more invisible system files
270 on every volume, which are all located at the volume root level (i.e.
271 "MacintoshHD:"). These system files are B<not> excluded automatically.
272 Your filter may use the following code to recognize invisible files or
273 directories (requires Mac::Files):
277 # invisible() -- returns 1 if file/directory is invisible,
278 # 0 if it's visible or undef if an error occurred
282 my ($fileCat, $fileInfo);
283 my $invisible_flag = 1 << 14;
285 if ( $fileCat = FSpGetCatInfo($file) ) {
286 if ($fileInfo = $fileCat->ioFlFndrInfo() ) {
287 return (($fileInfo->fdFlags & $invisible_flag) && 1);
293 Generally, invisible files are system files, unless an odd application
294 decides to use invisible files for its own purposes. To distinguish
295 such files from system files, you have to look at the B<type> and B<creator>
296 file attributes. The MacPerl built-in functions C<GetFileInfo(FILE)> and
297 C<SetFileInfo(CREATOR, TYPE, FILES)> offer access to these attributes
298 (see MacPerl.pm for details).
300 Files that appear on the desktop actually reside in an (hidden) directory
301 named "Desktop Folder" on the particular disk volume. Note that, although
302 all desktop files appear to be on the same "virtual" desktop, each disk
303 volume actually maintains its own "Desktop Folder" directory.
311 File::Find used to produce incorrect results if called recursively.
312 During the development of perl 5.8 this bug was fixed.
313 The first fixed version of File::Find was 1.01.
317 our @ISA = qw(Exporter);
318 our @EXPORT = qw(find finddepth);
325 require File::Basename;
328 # Should ideally be my() not our() but local() currently
329 # refuses to operate on lexicals
332 our ($wanted_callback, $avoid_nlink, $bydepth, $no_chdir, $follow,
333 $follow_skip, $full_check, $untaint, $untaint_skip, $untaint_pat,
334 $pre_process, $post_process, $dangling_symlinks);
339 return substr($cdir,0,rindex($cdir,'/')) if $fn eq $File::Find::current_dir;
341 $cdir = substr($cdir,0,rindex($cdir,'/')+1);
345 my $abs_name= $cdir . $fn;
347 if (substr($fn,0,3) eq '../') {
348 1 while $abs_name =~ s!/[^/]*/\.\./!/!;
354 # return the absolute name of a directory or file
355 sub contract_name_Mac {
359 if ($fn =~ /^(:+)(.*)$/) { # valid pathname starting with a ':'
361 my $colon_count = length ($1);
362 if ($colon_count == 1) {
363 $abs_name = $cdir . $2;
367 # need to move up the tree, but
368 # only if it's not a volume name
369 for (my $i=1; $i<$colon_count; $i++) {
370 unless ($cdir =~ /^[^:]+:$/) { # volume name
371 $cdir =~ s/[^:]+:$//;
377 $abs_name = $cdir . $2;
384 # $fn may be a valid path to a directory or file or (dangling)
385 # symlink, without a leading ':'
386 if ( (-e $fn) || (-l $fn) ) {
387 if ($fn =~ /^[^:]+:/) { # a volume name like DataHD:*
388 return $fn; # $fn is already an absolute path
391 $abs_name = $cdir . $fn;
395 else { # argh!, $fn is not a valid directory/file
401 sub PathCombine($$) {
402 my ($Base,$Name) = @_;
406 # $Name is the resolved symlink (always a full path on MacOS),
407 # i.e. there's no need to call contract_name_Mac()
410 # (simple) check for recursion
411 if ( ( $Base =~ /^$AbsName/) && (-d $AbsName) ) { # recursion
416 if (substr($Name,0,1) eq '/') {
420 $AbsName= contract_name($Base,$Name);
423 # (simple) check for recursion
424 my $newlen= length($AbsName);
425 if ($newlen <= length($Base)) {
426 if (($newlen == length($Base) || substr($Base,$newlen,1) eq '/')
427 && $AbsName eq substr($Base,0,$newlen))
436 sub Follow_SymLink($) {
439 my ($NewName,$DEV, $INO);
440 ($DEV, $INO)= lstat $AbsName;
443 if ($SLnkSeen{$DEV, $INO}++) {
444 if ($follow_skip < 2) {
445 die "$AbsName is encountered a second time";
451 $NewName= PathCombine($AbsName, readlink($AbsName));
452 unless(defined $NewName) {
453 if ($follow_skip < 2) {
454 die "$AbsName is a recursive symbolic link";
463 ($DEV, $INO) = lstat($AbsName);
464 return undef unless defined $DEV; # dangling symbolic link
467 if ($full_check && defined $DEV && $SLnkSeen{$DEV, $INO}++) {
468 if ( ($follow_skip < 1) || ((-d _) && ($follow_skip < 2)) ) {
469 die "$AbsName encountered a second time";
479 our($dir, $name, $fullname, $prune);
480 sub _find_dir_symlnk($$$);
483 # check whether or not a scalar variable is tainted
484 # (code straight from the Camel, 3rd ed., page 561)
487 my $nada = substr($arg, 0, 0); # zero-length
489 eval { eval "# $nada" };
490 return length($@) != 0;
495 die "invalid top directory" unless defined $_[0];
497 # This function must local()ize everything because callbacks may
498 # call find() or finddepth()
501 local ($wanted_callback, $avoid_nlink, $bydepth, $no_chdir, $follow,
502 $follow_skip, $full_check, $untaint, $untaint_skip, $untaint_pat,
503 $pre_process, $post_process, $dangling_symlinks);
504 local($dir, $name, $fullname, $prune);
506 my $cwd = $wanted->{bydepth} ? Cwd::fastcwd() : Cwd::getcwd();
507 my $cwd_untainted = $cwd;
509 $wanted_callback = $wanted->{wanted};
510 $bydepth = $wanted->{bydepth};
511 $pre_process = $wanted->{preprocess};
512 $post_process = $wanted->{postprocess};
513 $no_chdir = $wanted->{no_chdir};
514 $full_check = $wanted->{follow};
515 $follow = $full_check || $wanted->{follow_fast};
516 $follow_skip = $wanted->{follow_skip};
517 $untaint = $wanted->{untaint};
518 $untaint_pat = $wanted->{untaint_pattern};
519 $untaint_skip = $wanted->{untaint_skip};
520 $dangling_symlinks = $wanted->{dangling_symlinks};
522 # for compatibility reasons (find.pl, find2perl)
523 local our ($topdir, $topdev, $topino, $topmode, $topnlink);
525 # a symbolic link to a directory doesn't increase the link count
526 $avoid_nlink = $follow || $File::Find::dont_use_nlink;
528 my ($abs_dir, $Is_Dir);
531 foreach my $TOP (@_) {
535 ($topdev,$topino,$topmode,$topnlink) = $follow ? stat $top_item : lstat $top_item;
536 $top_item = ":$top_item"
537 if ( (-d _) && ( $top_item !~ /:/ ) );
540 $top_item =~ s|/\z|| unless $top_item eq '/';
541 ($topdev,$topino,$topmode,$topnlink) = $follow ? stat $top_item : lstat $top_item;
549 $cwd = "$cwd:" unless ($cwd =~ /:$/); # for safety
551 if ($top_item eq $File::Find::current_dir) {
555 $abs_dir = contract_name_Mac($cwd, $top_item);
556 unless (defined $abs_dir) {
557 warnings::warnif "Can't determine absolute path for $top_item (No such file or directory)\n";
564 if (substr($top_item,0,1) eq '/') {
565 $abs_dir = $top_item;
567 elsif ($top_item eq $File::Find::current_dir) {
570 else { # care about any ../
571 $abs_dir = contract_name("$cwd/",$top_item);
574 $abs_dir= Follow_SymLink($abs_dir);
575 unless (defined $abs_dir) {
576 if ($dangling_symlinks) {
577 if (ref $dangling_symlinks eq 'CODE') {
578 $dangling_symlinks->($top_item, $cwd);
580 warnings::warnif "$top_item is a dangling symbolic link\n";
587 _find_dir_symlnk($wanted, $abs_dir, $top_item);
593 unless (defined $topnlink) {
594 warnings::warnif "Can't stat $top_item: $!\n";
598 $top_item =~ s/\.dir\z// if $Is_VMS;
599 _find_dir($wanted, $top_item, $topnlink);
608 unless (($_,$dir) = File::Basename::fileparse($abs_dir)) {
610 ($dir,$_) = (':', $top_item); # $File::Find::dir, $_
613 ($dir,$_) = ('./', $top_item);
618 if (( $untaint ) && (is_tainted($dir) )) {
619 ( $abs_dir ) = $dir =~ m|$untaint_pat|;
620 unless (defined $abs_dir) {
621 if ($untaint_skip == 0) {
622 die "directory $dir is still tainted";
630 unless ($no_chdir || chdir $abs_dir) {
631 warnings::warnif "Couldn't chdir $abs_dir: $!\n";
635 $name = $abs_dir . $_; # $File::Find::name
637 { &$wanted_callback }; # protect against wild "next"
641 unless ( $no_chdir ) {
642 if ( ($check_t_cwd) && (($untaint) && (is_tainted($cwd) )) ) {
643 ( $cwd_untainted ) = $cwd =~ m|$untaint_pat|;
644 unless (defined $cwd_untainted) {
645 die "insecure cwd in find(depth)";
649 unless (chdir $cwd_untainted) {
650 die "Can't cd to $cwd: $!\n";
658 # $p_dir : "parent directory"
659 # $nlink : what came back from the stat
661 # chdir (if not no_chdir) to dir
664 my ($wanted, $p_dir, $nlink) = @_;
665 my ($CdLvl,$Level) = (0,0);
668 my ($subcount,$sub_nlink);
670 my $dir_name= $p_dir;
672 my $dir_rel = $File::Find::current_dir;
677 $dir_pref= ($p_dir =~ /:$/) ? $p_dir : "$p_dir:"; # preface
680 $dir_pref= ( $p_dir eq '/' ? '/' : "$p_dir/" );
683 local ($dir, $name, $prune, *DIR);
685 unless ( $no_chdir || ($p_dir eq $File::Find::current_dir)) {
687 if (( $untaint ) && (is_tainted($p_dir) )) {
688 ( $udir ) = $p_dir =~ m|$untaint_pat|;
689 unless (defined $udir) {
690 if ($untaint_skip == 0) {
691 die "directory $p_dir is still tainted";
698 unless (chdir $udir) {
699 warnings::warnif "Can't cd to $udir: $!\n";
704 # push the starting directory
705 push @Stack,[$CdLvl,$p_dir,$dir_rel,-1] if $bydepth;
708 $p_dir = $dir_pref; # ensure trailing ':'
711 while (defined $SE) {
713 $dir= $p_dir; # $File::Find::dir
714 $name= $dir_name; # $File::Find::name
715 $_= ($no_chdir ? $dir_name : $dir_rel ); # $_
716 # prune may happen here
718 { &$wanted_callback }; # protect against wild "next"
722 # change to that directory
723 unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
725 if ( ($untaint) && (($tainted) || ($tainted = is_tainted($dir_rel) )) ) {
726 ( $udir ) = $dir_rel =~ m|$untaint_pat|;
727 unless (defined $udir) {
728 if ($untaint_skip == 0) {
730 die "directory ($p_dir) $dir_rel is still tainted";
733 die "directory (" . ($p_dir ne '/' ? $p_dir : '') . "/) $dir_rel is still tainted";
735 } else { # $untaint_skip == 1
740 unless (chdir $udir) {
742 warnings::warnif "Can't cd to ($p_dir) $udir: $!\n";
745 warnings::warnif "Can't cd to (" .
746 ($p_dir ne '/' ? $p_dir : '') . "/) $udir: $!\n";
754 $dir_name = "$dir_name:" unless ($dir_name =~ /:$/);
757 $dir= $dir_name; # $File::Find::dir
759 # Get the list of files in the current directory.
760 unless (opendir DIR, ($no_chdir ? $dir_name : $File::Find::current_dir)) {
761 warnings::warnif "Can't opendir($dir_name): $!\n";
764 @filenames = readdir DIR;
766 @filenames = &$pre_process(@filenames) if $pre_process;
767 push @Stack,[$CdLvl,$dir_name,"",-2] if $post_process;
769 # default: use whatever was specifid
770 # (if $nlink >= 2, and $avoid_nlink == 0, this will switch back)
771 $no_nlink = $avoid_nlink;
772 # if dir has wrong nlink count, force switch to slower stat method
773 $no_nlink = 1 if ($nlink < 2);
775 if ($nlink == 2 && !$no_nlink) {
776 # This dir has no subdirectories.
777 for my $FN (@filenames) {
778 next if $FN =~ $File::Find::skip_pattern;
780 $name = $dir_pref . $FN; # $File::Find::name
781 $_ = ($no_chdir ? $name : $FN); # $_
782 { &$wanted_callback }; # protect against wild "next"
787 # This dir has subdirectories.
788 $subcount = $nlink - 2;
790 for my $FN (@filenames) {
791 next if $FN =~ $File::Find::skip_pattern;
792 if ($subcount > 0 || $no_nlink) {
793 # Seen all the subdirs?
794 # check for directoriness.
795 # stat is faster for a file in the current directory
796 $sub_nlink = (lstat ($no_chdir ? $dir_pref . $FN : $FN))[3];
800 $FN =~ s/\.dir\z// if $Is_VMS;
801 push @Stack,[$CdLvl,$dir_name,$FN,$sub_nlink];
804 $name = $dir_pref . $FN; # $File::Find::name
805 $_= ($no_chdir ? $name : $FN); # $_
806 { &$wanted_callback }; # protect against wild "next"
810 $name = $dir_pref . $FN; # $File::Find::name
811 $_= ($no_chdir ? $name : $FN); # $_
812 { &$wanted_callback }; # protect against wild "next"
818 while ( defined ($SE = pop @Stack) ) {
819 ($Level, $p_dir, $dir_rel, $nlink) = @$SE;
820 if ($CdLvl > $Level && !$no_chdir) {
823 $tmp = (':' x ($CdLvl-$Level)) . ':';
826 $tmp = join('/',('..') x ($CdLvl-$Level));
828 die "Can't cd to $dir_name" . $tmp
834 # $pdir always has a trailing ':', except for the starting dir,
835 # where $dir_rel eq ':'
836 $dir_name = "$p_dir$dir_rel";
837 $dir_pref = "$dir_name:";
840 $dir_name = ($p_dir eq '/' ? "/$dir_rel" : "$p_dir/$dir_rel");
841 $dir_pref = "$dir_name/";
844 if ( $nlink == -2 ) {
845 $name = $dir = $p_dir; # $File::Find::name / dir
846 $_ = $File::Find::current_dir;
847 &$post_process; # End-of-directory processing
849 elsif ( $nlink < 0 ) { # must be finddepth, report dirname now
852 if ($dir_rel eq ':') { # must be the top dir, where we started
853 $name =~ s|:$||; # $File::Find::name
854 $p_dir = "$p_dir:" unless ($p_dir =~ /:$/);
856 $dir = $p_dir; # $File::Find::dir
857 $_ = ($no_chdir ? $name : $dir_rel); # $_
860 if ( substr($name,-2) eq '/.' ) {
864 $_ = ($no_chdir ? $dir_name : $dir_rel );
865 if ( substr($_,-2) eq '/.' ) {
869 { &$wanted_callback }; # protect against wild "next"
872 push @Stack,[$CdLvl,$p_dir,$dir_rel,-1] if $bydepth;
882 # $dir_loc : absolute location of a dir
883 # $p_dir : "parent directory"
885 # chdir (if not no_chdir) to dir
887 sub _find_dir_symlnk($$$) {
888 my ($wanted, $dir_loc, $p_dir) = @_; # $dir_loc is the absolute directory
892 my $updir_loc = $dir_loc; # untainted parent directory
894 my $dir_name = $p_dir;
897 my $dir_rel = $File::Find::current_dir;
898 my $byd_flag; # flag for pending stack entry if $bydepth
903 $dir_pref = ($p_dir =~ /:$/) ? "$p_dir" : "$p_dir:";
904 $loc_pref = ($dir_loc =~ /:$/) ? "$dir_loc" : "$dir_loc:";
906 $dir_pref = ( $p_dir eq '/' ? '/' : "$p_dir/" );
907 $loc_pref = ( $dir_loc eq '/' ? '/' : "$dir_loc/" );
910 local ($dir, $name, $fullname, $prune, *DIR);
914 if (( $untaint ) && (is_tainted($dir_loc) )) {
915 ( $updir_loc ) = $dir_loc =~ m|$untaint_pat|; # parent dir, now untainted
916 # once untainted, $updir_loc is pushed on the stack (as parent directory);
917 # hence, we don't need to untaint the parent directory every time we chdir
919 unless (defined $updir_loc) {
920 if ($untaint_skip == 0) {
921 die "directory $dir_loc is still tainted";
928 $ok = chdir($updir_loc) unless ($p_dir eq $File::Find::current_dir);
930 warnings::warnif "Can't cd to $updir_loc: $!\n";
935 push @Stack,[$dir_loc,$updir_loc,$p_dir,$dir_rel,-1] if $bydepth;
938 $p_dir = $dir_pref; # ensure trailing ':'
941 while (defined $SE) {
944 # change (back) to parent directory (always untainted)
946 unless (chdir $updir_loc) {
947 warnings::warnif "Can't cd to $updir_loc: $!\n";
951 $dir= $p_dir; # $File::Find::dir
952 $name= $dir_name; # $File::Find::name
953 $_= ($no_chdir ? $dir_name : $dir_rel ); # $_
954 $fullname= $dir_loc; # $File::Find::fullname
955 # prune may happen here
957 lstat($_); # make sure file tests with '_' work
958 { &$wanted_callback }; # protect against wild "next"
962 # change to that directory
963 unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
964 $updir_loc = $dir_loc;
965 if ( ($untaint) && (($tainted) || ($tainted = is_tainted($dir_loc) )) ) {
966 # untaint $dir_loc, what will be pushed on the stack as (untainted) parent dir
967 ( $updir_loc ) = $dir_loc =~ m|$untaint_pat|;
968 unless (defined $updir_loc) {
969 if ($untaint_skip == 0) {
970 die "directory $dir_loc is still tainted";
977 unless (chdir $updir_loc) {
978 warnings::warnif "Can't cd to $updir_loc: $!\n";
984 $dir_name = "$dir_name:" unless ($dir_name =~ /:$/);
987 $dir = $dir_name; # $File::Find::dir
989 # Get the list of files in the current directory.
990 unless (opendir DIR, ($no_chdir ? $dir_loc : $File::Find::current_dir)) {
991 warnings::warnif "Can't opendir($dir_loc): $!\n";
994 @filenames = readdir DIR;
997 for my $FN (@filenames) {
998 next if $FN =~ $File::Find::skip_pattern;
1000 # follow symbolic links / do an lstat
1001 $new_loc = Follow_SymLink($loc_pref.$FN);
1003 # ignore if invalid symlink
1004 next unless defined $new_loc;
1007 push @Stack,[$new_loc,$updir_loc,$dir_name,$FN,1];
1010 $fullname = $new_loc; # $File::Find::fullname
1011 $name = $dir_pref . $FN; # $File::Find::name
1012 $_ = ($no_chdir ? $name : $FN); # $_
1013 { &$wanted_callback }; # protect against wild "next"
1019 while (defined($SE = pop @Stack)) {
1020 ($dir_loc, $updir_loc, $p_dir, $dir_rel, $byd_flag) = @$SE;
1022 # $p_dir always has a trailing ':', except for the starting dir,
1023 # where $dir_rel eq ':'
1024 $dir_name = "$p_dir$dir_rel";
1025 $dir_pref = "$dir_name:";
1026 $loc_pref = ($dir_loc =~ /:$/) ? $dir_loc : "$dir_loc:";
1029 $dir_name = ($p_dir eq '/' ? "/$dir_rel" : "$p_dir/$dir_rel");
1030 $dir_pref = "$dir_name/";
1031 $loc_pref = "$dir_loc/";
1033 if ( $byd_flag < 0 ) { # must be finddepth, report dirname now
1034 unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
1035 unless (chdir $updir_loc) { # $updir_loc (parent dir) is always untainted
1036 warnings::warnif "Can't cd to $updir_loc: $!\n";
1040 $fullname = $dir_loc; # $File::Find::fullname
1041 $name = $dir_name; # $File::Find::name
1043 if ($dir_rel eq ':') { # must be the top dir, where we started
1044 $name =~ s|:$||; # $File::Find::name
1045 $p_dir = "$p_dir:" unless ($p_dir =~ /:$/);
1047 $dir = $p_dir; # $File::Find::dir
1048 $_ = ($no_chdir ? $name : $dir_rel); # $_
1051 if ( substr($name,-2) eq '/.' ) {
1052 $name =~ s|/\.$||; # $File::Find::name
1054 $dir = $p_dir; # $File::Find::dir
1055 $_ = ($no_chdir ? $dir_name : $dir_rel); # $_
1056 if ( substr($_,-2) eq '/.' ) {
1061 lstat($_); # make sure file tests with '_' work
1062 { &$wanted_callback }; # protect against wild "next"
1065 push @Stack,[$dir_loc, $updir_loc, $p_dir, $dir_rel,-1] if $bydepth;
1075 if ( ref($wanted) eq 'HASH' ) {
1076 if ( $wanted->{follow} || $wanted->{follow_fast}) {
1077 $wanted->{follow_skip} = 1 unless defined $wanted->{follow_skip};
1079 if ( $wanted->{untaint} ) {
1080 $wanted->{untaint_pattern} = $File::Find::untaint_pattern
1081 unless defined $wanted->{untaint_pattern};
1082 $wanted->{untaint_skip} = 0 unless defined $wanted->{untaint_skip};
1087 return { wanted => $wanted };
1093 _find_opt(wrap_wanted($wanted), @_);
1097 my $wanted = wrap_wanted(shift);
1098 $wanted->{bydepth} = 1;
1099 _find_opt($wanted, @_);
1103 $File::Find::skip_pattern = qr/^\.{1,2}\z/;
1104 $File::Find::untaint_pattern = qr|^([-+@\w./]+)$|;
1106 # These are hard-coded for now, but may move to hint files.
1109 $File::Find::dont_use_nlink = 1;
1111 elsif ($^O eq 'MacOS') {
1113 $File::Find::dont_use_nlink = 1;
1114 $File::Find::skip_pattern = qr/^Icon\015\z/;
1115 $File::Find::untaint_pattern = qr|^(.+)$|;
1118 # this _should_ work properly on all platforms
1119 # where File::Find can be expected to work
1120 $File::Find::current_dir = File::Spec->curdir || '.';
1122 $File::Find::dont_use_nlink = 1
1123 if $^O eq 'os2' || $^O eq 'dos' || $^O eq 'amigaos' || $^O eq 'MSWin32' ||
1124 $^O eq 'cygwin' || $^O eq 'epoc' || $^O eq 'NetWare';
1126 # Set dont_use_nlink in your hint file if your system's stat doesn't
1127 # report the number of links in a directory as an indication
1128 # of the number of files.
1129 # See, e.g. hints/machten.sh for MachTen 2.2.
1130 unless ($File::Find::dont_use_nlink) {
1132 $File::Find::dont_use_nlink = 1 if ($Config::Config{'dont_use_nlink'});
1135 # We need a function that checks if a scalar is tainted. Either use the
1136 # Scalar::Util module's tainted() function or our (slower) pure Perl
1137 # fallback is_tainted_pp()
1140 eval { require Scalar::Util };
1141 *is_tainted = $@ ? \&is_tainted_pp : \&Scalar::Util::tainted;