5 use warnings::register;
12 File::Find - Traverse a directory tree.
17 find(\&wanted, @directories_to_seach);
21 finddepth(\&wanted, @directories_to_search);
25 find({ wanted => \&process, follow => 1 }, '.');
29 These are functions for searching through directory trees doing work
30 on each file found similar to the Unix I<find> command. File::Find
31 exports two functions, C<find> and C<finddepth>. They work similarly
32 but have subtle differences.
38 find(\&wanted, @directories);
39 find(\%options, @directories);
41 find() does a breadth-first search over the given @directories in the
42 order they are given. In essense, it works from the top down.
44 For each file or directory found the &wanted subroutine is called (see
45 below for details). Additionally, for each directory found it will go
46 into that directory and continue the search.
50 finddepth(\&wanted, @directories);
51 finddepth(\%options, @directories);
53 finddepth() works just like find() except it does a depth-first search.
54 It works from the bottom of the directory tree up.
60 The first argument to find() is either a hash reference describing the
61 operations to be performed for each file, or a code reference. The
62 code reference is described in L<The wanted function> below.
64 Here are the possible keys for the hash:
70 The value should be a code reference. This code reference is
71 described in L<The wanted function> below.
75 Reports the name of a directory only AFTER all its entries
76 have been reported. Entry point finddepth() is a shortcut for
77 specifying C<{ bydepth =E<gt> 1 }> in the first argument of find().
81 The value should be a code reference. This code reference is used to
82 preprocess the current directory. The name of currently processed
83 directory is in $File::Find::dir. Your preprocessing function is
84 called after readdir() but before the loop that calls the wanted()
85 function. It is called with a list of strings (actually file/directory
86 names) and is expected to return a list of strings. The code can be
87 used to sort the file/directory names alphabetically, numerically,
88 or to filter out directory entries based on their name alone. When
89 I<follow> or I<follow_fast> are in effect, C<preprocess> is a no-op.
93 The value should be a code reference. It is invoked just before leaving
94 the currently processed directory. It is called in void context with no
95 arguments. The name of the current directory is in $File::Find::dir. This
96 hook is handy for summarizing a directory, such as calculating its disk
97 usage. When I<follow> or I<follow_fast> are in effect, C<postprocess> is a
102 Causes symbolic links to be followed. Since directory trees with symbolic
103 links (followed) may contain files more than once and may even have
104 cycles, a hash has to be built up with an entry for each file.
105 This might be expensive both in space and time for a large
106 directory tree. See I<follow_fast> and I<follow_skip> below.
107 If either I<follow> or I<follow_fast> is in effect:
113 It is guaranteed that an I<lstat> has been called before the user's
114 I<wanted()> function is called. This enables fast file checks involving S< _>.
118 There is a variable C<$File::Find::fullname> which holds the absolute
119 pathname of the file with all symbolic links resolved
125 This is similar to I<follow> except that it may report some files more
126 than once. It does detect cycles, however. Since only symbolic links
127 have to be hashed, this is much cheaper both in space and time. If
128 processing a file more than once (by the user's I<wanted()> function)
129 is worse than just taking time, the option I<follow> should be used.
133 C<follow_skip==1>, which is the default, causes all files which are
134 neither directories nor symbolic links to be ignored if they are about
135 to be processed a second time. If a directory or a symbolic link
136 are about to be processed a second time, File::Find dies.
137 C<follow_skip==0> causes File::Find to die if any file is about to be
138 processed a second time.
139 C<follow_skip==2> causes File::Find to ignore any duplicate files and
140 directories but to proceed normally otherwise.
142 =item C<dangling_symlinks>
144 If true and a code reference, will be called with the symbolic link
145 name and the directory it lives in as arguments. Otherwise, if true
146 and warnings are on, warning "symbolic_link_name is a dangling
147 symbolic link\n" will be issued. If false, the dangling symbolic link
148 will be silently ignored.
152 Does not C<chdir()> to each directory as it recurses. The wanted()
153 function will need to be aware of this, of course. In this case,
154 C<$_> will be the same as C<$File::Find::name>.
158 If find is used in taint-mode (-T command line switch or if EUID != UID
159 or if EGID != GID) then internally directory names have to be untainted
160 before they can be chdir'ed to. Therefore they are checked against a regular
161 expression I<untaint_pattern>. Note that all names passed to the user's
162 I<wanted()> function are still tainted. If this option is used while
163 not in taint-mode, C<untaint> is a no-op.
165 =item C<untaint_pattern>
167 See above. This should be set using the C<qr> quoting operator.
168 The default is set to C<qr|^([-+@\w./]+)$|>.
169 Note that the parentheses are vital.
171 =item C<untaint_skip>
173 If set, a directory which fails the I<untaint_pattern> is skipped,
174 including all its sub-directories. The default is to 'die' in such a case.
178 =head2 The wanted function
180 The wanted() function does whatever verifications you want on each
181 file and directory. It takes no arguments but rather does its work
182 through a collection of variables.
186 =item C<$File::Find::dir> is the current directory name,
188 =item C<$_> is the current filename within that directory
190 =item C<$File::Find::name> is the complete pathname to the file.
194 Don't modify these variables.
196 For example, when examining the file /some/path/foo.ext you will have:
198 $File::Find::dir = /some/path/
200 $File::Find::name = /some/path/foo.ext
202 You are chdir()'d toC<$File::Find::dir> when the function is called,
203 unless C<no_chdir> was specified. Note that when changing to
204 directories is in effect the root directory (F</>) is a somewhat
205 special case inasmuch as the concatenation of C<$File::Find::dir>,
206 C<'/'> and C<$_> is not literally equal to C<$File::Find::name>. The
207 table below summarizes all variants:
209 $File::Find::name $File::Find::dir $_
211 no_chdir=>0 /etc / etc
219 When <follow> or <follow_fast> are in effect, there is
220 also a C<$File::Find::fullname>. The function may set
221 C<$File::Find::prune> to prune the tree unless C<bydepth> was
222 specified. Unless C<follow> or C<follow_fast> is specified, for
223 compatibility reasons (find.pl, find2perl) there are in addition the
224 following globals available: C<$File::Find::topdir>,
225 C<$File::Find::topdev>, C<$File::Find::topino>,
226 C<$File::Find::topmode> and C<$File::Find::topnlink>.
228 This library is useful for the C<find2perl> tool, which when fed,
230 find2perl / -name .nfs\* -mtime +7 \
231 -exec rm -f {} \; -o -fstype nfs -prune
233 produces something like:
237 (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_)) &&
241 ($nlink || (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_))) &&
243 ($File::Find::prune = 1);
246 Notice the C<_> in the above C<int(-M _)>: the C<_> is a magical
247 filehandle that caches the information from the preceding
248 stat(), lstat(), or filetest.
250 Here's another interesting wanted function. It will find all symbolic
251 links that don't resolve:
254 -l && !-e && print "bogus link: $File::Find::name\n";
257 See also the script C<pfind> on CPAN for a nice application of this
262 If you run your program with the C<-w> switch, or if you use the
263 C<warnings> pragma, File::Find will report warnings for several weird
264 situations. You can disable these warnings by putting the statement
266 no warnings 'File::Find';
268 in the appropriate scope. See L<perllexwarn> for more info about lexical
275 =item $dont_use_nlink
277 You can set the variable C<$File::Find::dont_use_nlink> to 1, if you want to
278 force File::Find to always stat directories. This was used for file systems
279 that do not have an C<nlink> count matching the number of sub-directories.
280 Examples are ISO-9660 (CD-ROM), AFS, HPFS (OS/2 file system), FAT (DOS file
281 system) and a couple of others.
283 You shouldn't need to set this variable, since File::Find should now detect
284 such file systems on-the-fly and switch itself to using stat. This works even
285 for parts of your file system, like a mounted CD-ROM.
287 If you do set C<$File::Find::dont_use_nlink> to 1, you will notice slow-downs.
291 Be aware that the option to follow symbolic links can be dangerous.
292 Depending on the structure of the directory tree (including symbolic
293 links to directories) you might traverse a given (physical) directory
294 more than once (only if C<follow_fast> is in effect).
295 Furthermore, deleting or changing files in a symbolically linked directory
296 might cause very unpleasant surprises, since you delete or change files
297 in an unknown directory.
307 Mac OS (Classic) users should note a few differences:
313 The path separator is ':', not '/', and the current directory is denoted
314 as ':', not '.'. You should be careful about specifying relative pathnames.
315 While a full path always begins with a volume name, a relative pathname
316 should always begin with a ':'. If specifying a volume name only, a
317 trailing ':' is required.
321 C<$File::Find::dir> is guaranteed to end with a ':'. If C<$_>
322 contains the name of a directory, that name may or may not end with a
323 ':'. Likewise, C<$File::Find::name>, which contains the complete
324 pathname to that directory, and C<$File::Find::fullname>, which holds
325 the absolute pathname of that directory with all symbolic links resolved,
326 may or may not end with a ':'.
330 The default C<untaint_pattern> (see above) on Mac OS is set to
331 C<qr|^(.+)$|>. Note that the parentheses are vital.
335 The invisible system file "Icon\015" is ignored. While this file may
336 appear in every directory, there are some more invisible system files
337 on every volume, which are all located at the volume root level (i.e.
338 "MacintoshHD:"). These system files are B<not> excluded automatically.
339 Your filter may use the following code to recognize invisible files or
340 directories (requires Mac::Files):
344 # invisible() -- returns 1 if file/directory is invisible,
345 # 0 if it's visible or undef if an error occurred
349 my ($fileCat, $fileInfo);
350 my $invisible_flag = 1 << 14;
352 if ( $fileCat = FSpGetCatInfo($file) ) {
353 if ($fileInfo = $fileCat->ioFlFndrInfo() ) {
354 return (($fileInfo->fdFlags & $invisible_flag) && 1);
360 Generally, invisible files are system files, unless an odd application
361 decides to use invisible files for its own purposes. To distinguish
362 such files from system files, you have to look at the B<type> and B<creator>
363 file attributes. The MacPerl built-in functions C<GetFileInfo(FILE)> and
364 C<SetFileInfo(CREATOR, TYPE, FILES)> offer access to these attributes
365 (see MacPerl.pm for details).
367 Files that appear on the desktop actually reside in an (hidden) directory
368 named "Desktop Folder" on the particular disk volume. Note that, although
369 all desktop files appear to be on the same "virtual" desktop, each disk
370 volume actually maintains its own "Desktop Folder" directory.
378 File::Find used to produce incorrect results if called recursively.
379 During the development of perl 5.8 this bug was fixed.
380 The first fixed version of File::Find was 1.01.
384 our @ISA = qw(Exporter);
385 our @EXPORT = qw(find finddepth);
392 require File::Basename;
395 # Should ideally be my() not our() but local() currently
396 # refuses to operate on lexicals
399 our ($wanted_callback, $avoid_nlink, $bydepth, $no_chdir, $follow,
400 $follow_skip, $full_check, $untaint, $untaint_skip, $untaint_pat,
401 $pre_process, $post_process, $dangling_symlinks);
406 return substr($cdir,0,rindex($cdir,'/')) if $fn eq $File::Find::current_dir;
408 $cdir = substr($cdir,0,rindex($cdir,'/')+1);
412 my $abs_name= $cdir . $fn;
414 if (substr($fn,0,3) eq '../') {
415 1 while $abs_name =~ s!/[^/]*/\.\./!/!;
421 # return the absolute name of a directory or file
422 sub contract_name_Mac {
426 if ($fn =~ /^(:+)(.*)$/) { # valid pathname starting with a ':'
428 my $colon_count = length ($1);
429 if ($colon_count == 1) {
430 $abs_name = $cdir . $2;
434 # need to move up the tree, but
435 # only if it's not a volume name
436 for (my $i=1; $i<$colon_count; $i++) {
437 unless ($cdir =~ /^[^:]+:$/) { # volume name
438 $cdir =~ s/[^:]+:$//;
444 $abs_name = $cdir . $2;
451 # $fn may be a valid path to a directory or file or (dangling)
452 # symlink, without a leading ':'
453 if ( (-e $fn) || (-l $fn) ) {
454 if ($fn =~ /^[^:]+:/) { # a volume name like DataHD:*
455 return $fn; # $fn is already an absolute path
458 $abs_name = $cdir . $fn;
462 else { # argh!, $fn is not a valid directory/file
468 sub PathCombine($$) {
469 my ($Base,$Name) = @_;
473 # $Name is the resolved symlink (always a full path on MacOS),
474 # i.e. there's no need to call contract_name_Mac()
477 # (simple) check for recursion
478 if ( ( $Base =~ /^$AbsName/) && (-d $AbsName) ) { # recursion
483 if (substr($Name,0,1) eq '/') {
487 $AbsName= contract_name($Base,$Name);
490 # (simple) check for recursion
491 my $newlen= length($AbsName);
492 if ($newlen <= length($Base)) {
493 if (($newlen == length($Base) || substr($Base,$newlen,1) eq '/')
494 && $AbsName eq substr($Base,0,$newlen))
503 sub Follow_SymLink($) {
506 my ($NewName,$DEV, $INO);
507 ($DEV, $INO)= lstat $AbsName;
510 if ($SLnkSeen{$DEV, $INO}++) {
511 if ($follow_skip < 2) {
512 die "$AbsName is encountered a second time";
518 $NewName= PathCombine($AbsName, readlink($AbsName));
519 unless(defined $NewName) {
520 if ($follow_skip < 2) {
521 die "$AbsName is a recursive symbolic link";
530 ($DEV, $INO) = lstat($AbsName);
531 return undef unless defined $DEV; # dangling symbolic link
534 if ($full_check && defined $DEV && $SLnkSeen{$DEV, $INO}++) {
535 if ( ($follow_skip < 1) || ((-d _) && ($follow_skip < 2)) ) {
536 die "$AbsName encountered a second time";
546 our($dir, $name, $fullname, $prune);
547 sub _find_dir_symlnk($$$);
550 # check whether or not a scalar variable is tainted
551 # (code straight from the Camel, 3rd ed., page 561)
554 my $nada = substr($arg, 0, 0); # zero-length
556 eval { eval "# $nada" };
557 return length($@) != 0;
562 die "invalid top directory" unless defined $_[0];
564 # This function must local()ize everything because callbacks may
565 # call find() or finddepth()
568 local ($wanted_callback, $avoid_nlink, $bydepth, $no_chdir, $follow,
569 $follow_skip, $full_check, $untaint, $untaint_skip, $untaint_pat,
570 $pre_process, $post_process, $dangling_symlinks);
571 local($dir, $name, $fullname, $prune, $_);
573 my $cwd = $wanted->{bydepth} ? Cwd::fastcwd() : Cwd::getcwd();
574 my $cwd_untainted = $cwd;
576 $wanted_callback = $wanted->{wanted};
577 $bydepth = $wanted->{bydepth};
578 $pre_process = $wanted->{preprocess};
579 $post_process = $wanted->{postprocess};
580 $no_chdir = $wanted->{no_chdir};
581 $full_check = $wanted->{follow};
582 $follow = $full_check || $wanted->{follow_fast};
583 $follow_skip = $wanted->{follow_skip};
584 $untaint = $wanted->{untaint};
585 $untaint_pat = $wanted->{untaint_pattern};
586 $untaint_skip = $wanted->{untaint_skip};
587 $dangling_symlinks = $wanted->{dangling_symlinks};
589 # for compatibility reasons (find.pl, find2perl)
590 local our ($topdir, $topdev, $topino, $topmode, $topnlink);
592 # a symbolic link to a directory doesn't increase the link count
593 $avoid_nlink = $follow || $File::Find::dont_use_nlink;
595 my ($abs_dir, $Is_Dir);
598 foreach my $TOP (@_) {
602 ($topdev,$topino,$topmode,$topnlink) = $follow ? stat $top_item : lstat $top_item;
603 $top_item = ":$top_item"
604 if ( (-d _) && ( $top_item !~ /:/ ) );
607 $top_item =~ s|/\z|| unless $top_item eq '/';
608 ($topdev,$topino,$topmode,$topnlink) = $follow ? stat $top_item : lstat $top_item;
616 $cwd = "$cwd:" unless ($cwd =~ /:$/); # for safety
618 if ($top_item eq $File::Find::current_dir) {
622 $abs_dir = contract_name_Mac($cwd, $top_item);
623 unless (defined $abs_dir) {
624 warnings::warnif "Can't determine absolute path for $top_item (No such file or directory)\n";
631 if (substr($top_item,0,1) eq '/') {
632 $abs_dir = $top_item;
634 elsif ($top_item eq $File::Find::current_dir) {
637 else { # care about any ../
638 $abs_dir = contract_name("$cwd/",$top_item);
641 $abs_dir= Follow_SymLink($abs_dir);
642 unless (defined $abs_dir) {
643 if ($dangling_symlinks) {
644 if (ref $dangling_symlinks eq 'CODE') {
645 $dangling_symlinks->($top_item, $cwd);
647 warnings::warnif "$top_item is a dangling symbolic link\n";
654 _find_dir_symlnk($wanted, $abs_dir, $top_item);
660 unless (defined $topnlink) {
661 warnings::warnif "Can't stat $top_item: $!\n";
665 $top_item =~ s/\.dir\z// if $Is_VMS;
666 _find_dir($wanted, $top_item, $topnlink);
675 unless (($_,$dir) = File::Basename::fileparse($abs_dir)) {
677 ($dir,$_) = (':', $top_item); # $File::Find::dir, $_
680 ($dir,$_) = ('./', $top_item);
685 if (( $untaint ) && (is_tainted($dir) )) {
686 ( $abs_dir ) = $dir =~ m|$untaint_pat|;
687 unless (defined $abs_dir) {
688 if ($untaint_skip == 0) {
689 die "directory $dir is still tainted";
697 unless ($no_chdir || chdir $abs_dir) {
698 warnings::warnif "Couldn't chdir $abs_dir: $!\n";
702 $name = $abs_dir . $_; # $File::Find::name
704 { $wanted_callback->() }; # protect against wild "next"
708 unless ( $no_chdir ) {
709 if ( ($check_t_cwd) && (($untaint) && (is_tainted($cwd) )) ) {
710 ( $cwd_untainted ) = $cwd =~ m|$untaint_pat|;
711 unless (defined $cwd_untainted) {
712 die "insecure cwd in find(depth)";
716 unless (chdir $cwd_untainted) {
717 die "Can't cd to $cwd: $!\n";
725 # $p_dir : "parent directory"
726 # $nlink : what came back from the stat
728 # chdir (if not no_chdir) to dir
731 my ($wanted, $p_dir, $nlink) = @_;
732 my ($CdLvl,$Level) = (0,0);
735 my ($subcount,$sub_nlink);
737 my $dir_name= $p_dir;
739 my $dir_rel = $File::Find::current_dir;
744 $dir_pref= ($p_dir =~ /:$/) ? $p_dir : "$p_dir:"; # preface
747 $dir_pref= ( $p_dir eq '/' ? '/' : "$p_dir/" );
750 local ($dir, $name, $prune, *DIR);
752 unless ( $no_chdir || ($p_dir eq $File::Find::current_dir)) {
754 if (( $untaint ) && (is_tainted($p_dir) )) {
755 ( $udir ) = $p_dir =~ m|$untaint_pat|;
756 unless (defined $udir) {
757 if ($untaint_skip == 0) {
758 die "directory $p_dir is still tainted";
765 unless (chdir $udir) {
766 warnings::warnif "Can't cd to $udir: $!\n";
771 # push the starting directory
772 push @Stack,[$CdLvl,$p_dir,$dir_rel,-1] if $bydepth;
775 $p_dir = $dir_pref; # ensure trailing ':'
778 while (defined $SE) {
780 $dir= $p_dir; # $File::Find::dir
781 $name= $dir_name; # $File::Find::name
782 $_= ($no_chdir ? $dir_name : $dir_rel ); # $_
783 # prune may happen here
785 { $wanted_callback->() }; # protect against wild "next"
789 # change to that directory
790 unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
792 if ( ($untaint) && (($tainted) || ($tainted = is_tainted($dir_rel) )) ) {
793 ( $udir ) = $dir_rel =~ m|$untaint_pat|;
794 unless (defined $udir) {
795 if ($untaint_skip == 0) {
797 die "directory ($p_dir) $dir_rel is still tainted";
800 die "directory (" . ($p_dir ne '/' ? $p_dir : '') . "/) $dir_rel is still tainted";
802 } else { # $untaint_skip == 1
807 unless (chdir $udir) {
809 warnings::warnif "Can't cd to ($p_dir) $udir: $!\n";
812 warnings::warnif "Can't cd to (" .
813 ($p_dir ne '/' ? $p_dir : '') . "/) $udir: $!\n";
821 $dir_name = "$dir_name:" unless ($dir_name =~ /:$/);
824 $dir= $dir_name; # $File::Find::dir
826 # Get the list of files in the current directory.
827 unless (opendir DIR, ($no_chdir ? $dir_name : $File::Find::current_dir)) {
828 warnings::warnif "Can't opendir($dir_name): $!\n";
831 @filenames = readdir DIR;
833 @filenames = $pre_process->(@filenames) if $pre_process;
834 push @Stack,[$CdLvl,$dir_name,"",-2] if $post_process;
836 # default: use whatever was specifid
837 # (if $nlink >= 2, and $avoid_nlink == 0, this will switch back)
838 $no_nlink = $avoid_nlink;
839 # if dir has wrong nlink count, force switch to slower stat method
840 $no_nlink = 1 if ($nlink < 2);
842 if ($nlink == 2 && !$no_nlink) {
843 # This dir has no subdirectories.
844 for my $FN (@filenames) {
845 next if $FN =~ $File::Find::skip_pattern;
847 $name = $dir_pref . $FN; # $File::Find::name
848 $_ = ($no_chdir ? $name : $FN); # $_
849 { $wanted_callback->() }; # protect against wild "next"
854 # This dir has subdirectories.
855 $subcount = $nlink - 2;
857 for my $FN (@filenames) {
858 next if $FN =~ $File::Find::skip_pattern;
859 if ($subcount > 0 || $no_nlink) {
860 # Seen all the subdirs?
861 # check for directoriness.
862 # stat is faster for a file in the current directory
863 $sub_nlink = (lstat ($no_chdir ? $dir_pref . $FN : $FN))[3];
867 $FN =~ s/\.dir\z// if $Is_VMS;
868 push @Stack,[$CdLvl,$dir_name,$FN,$sub_nlink];
871 $name = $dir_pref . $FN; # $File::Find::name
872 $_= ($no_chdir ? $name : $FN); # $_
873 { $wanted_callback->() }; # protect against wild "next"
877 $name = $dir_pref . $FN; # $File::Find::name
878 $_= ($no_chdir ? $name : $FN); # $_
879 { $wanted_callback->() }; # protect against wild "next"
885 while ( defined ($SE = pop @Stack) ) {
886 ($Level, $p_dir, $dir_rel, $nlink) = @$SE;
887 if ($CdLvl > $Level && !$no_chdir) {
890 $tmp = (':' x ($CdLvl-$Level)) . ':';
893 $tmp = join('/',('..') x ($CdLvl-$Level));
895 die "Can't cd to $dir_name" . $tmp
901 # $pdir always has a trailing ':', except for the starting dir,
902 # where $dir_rel eq ':'
903 $dir_name = "$p_dir$dir_rel";
904 $dir_pref = "$dir_name:";
907 $dir_name = ($p_dir eq '/' ? "/$dir_rel" : "$p_dir/$dir_rel");
908 $dir_pref = "$dir_name/";
911 if ( $nlink == -2 ) {
912 $name = $dir = $p_dir; # $File::Find::name / dir
913 $_ = $File::Find::current_dir;
914 $post_process->(); # End-of-directory processing
916 elsif ( $nlink < 0 ) { # must be finddepth, report dirname now
919 if ($dir_rel eq ':') { # must be the top dir, where we started
920 $name =~ s|:$||; # $File::Find::name
921 $p_dir = "$p_dir:" unless ($p_dir =~ /:$/);
923 $dir = $p_dir; # $File::Find::dir
924 $_ = ($no_chdir ? $name : $dir_rel); # $_
927 if ( substr($name,-2) eq '/.' ) {
928 substr($name, length($name) == 2 ? -1 : -2) = '';
931 $_ = ($no_chdir ? $dir_name : $dir_rel );
932 if ( substr($_,-2) eq '/.' ) {
933 substr($_, length($_) == 2 ? -1 : -2) = '';
936 { $wanted_callback->() }; # protect against wild "next"
939 push @Stack,[$CdLvl,$p_dir,$dir_rel,-1] if $bydepth;
949 # $dir_loc : absolute location of a dir
950 # $p_dir : "parent directory"
952 # chdir (if not no_chdir) to dir
954 sub _find_dir_symlnk($$$) {
955 my ($wanted, $dir_loc, $p_dir) = @_; # $dir_loc is the absolute directory
959 my $updir_loc = $dir_loc; # untainted parent directory
961 my $dir_name = $p_dir;
964 my $dir_rel = $File::Find::current_dir;
965 my $byd_flag; # flag for pending stack entry if $bydepth
970 $dir_pref = ($p_dir =~ /:$/) ? "$p_dir" : "$p_dir:";
971 $loc_pref = ($dir_loc =~ /:$/) ? "$dir_loc" : "$dir_loc:";
973 $dir_pref = ( $p_dir eq '/' ? '/' : "$p_dir/" );
974 $loc_pref = ( $dir_loc eq '/' ? '/' : "$dir_loc/" );
977 local ($dir, $name, $fullname, $prune, *DIR);
981 if (( $untaint ) && (is_tainted($dir_loc) )) {
982 ( $updir_loc ) = $dir_loc =~ m|$untaint_pat|; # parent dir, now untainted
983 # once untainted, $updir_loc is pushed on the stack (as parent directory);
984 # hence, we don't need to untaint the parent directory every time we chdir
986 unless (defined $updir_loc) {
987 if ($untaint_skip == 0) {
988 die "directory $dir_loc is still tainted";
995 $ok = chdir($updir_loc) unless ($p_dir eq $File::Find::current_dir);
997 warnings::warnif "Can't cd to $updir_loc: $!\n";
1002 push @Stack,[$dir_loc,$updir_loc,$p_dir,$dir_rel,-1] if $bydepth;
1005 $p_dir = $dir_pref; # ensure trailing ':'
1008 while (defined $SE) {
1011 # change (back) to parent directory (always untainted)
1012 unless ($no_chdir) {
1013 unless (chdir $updir_loc) {
1014 warnings::warnif "Can't cd to $updir_loc: $!\n";
1018 $dir= $p_dir; # $File::Find::dir
1019 $name= $dir_name; # $File::Find::name
1020 $_= ($no_chdir ? $dir_name : $dir_rel ); # $_
1021 $fullname= $dir_loc; # $File::Find::fullname
1022 # prune may happen here
1024 lstat($_); # make sure file tests with '_' work
1025 { $wanted_callback->() }; # protect against wild "next"
1029 # change to that directory
1030 unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
1031 $updir_loc = $dir_loc;
1032 if ( ($untaint) && (($tainted) || ($tainted = is_tainted($dir_loc) )) ) {
1033 # untaint $dir_loc, what will be pushed on the stack as (untainted) parent dir
1034 ( $updir_loc ) = $dir_loc =~ m|$untaint_pat|;
1035 unless (defined $updir_loc) {
1036 if ($untaint_skip == 0) {
1037 die "directory $dir_loc is still tainted";
1044 unless (chdir $updir_loc) {
1045 warnings::warnif "Can't cd to $updir_loc: $!\n";
1051 $dir_name = "$dir_name:" unless ($dir_name =~ /:$/);
1054 $dir = $dir_name; # $File::Find::dir
1056 # Get the list of files in the current directory.
1057 unless (opendir DIR, ($no_chdir ? $dir_loc : $File::Find::current_dir)) {
1058 warnings::warnif "Can't opendir($dir_loc): $!\n";
1061 @filenames = readdir DIR;
1064 for my $FN (@filenames) {
1065 next if $FN =~ $File::Find::skip_pattern;
1067 # follow symbolic links / do an lstat
1068 $new_loc = Follow_SymLink($loc_pref.$FN);
1070 # ignore if invalid symlink
1071 next unless defined $new_loc;
1074 push @Stack,[$new_loc,$updir_loc,$dir_name,$FN,1];
1077 $fullname = $new_loc; # $File::Find::fullname
1078 $name = $dir_pref . $FN; # $File::Find::name
1079 $_ = ($no_chdir ? $name : $FN); # $_
1080 { $wanted_callback->() }; # protect against wild "next"
1086 while (defined($SE = pop @Stack)) {
1087 ($dir_loc, $updir_loc, $p_dir, $dir_rel, $byd_flag) = @$SE;
1089 # $p_dir always has a trailing ':', except for the starting dir,
1090 # where $dir_rel eq ':'
1091 $dir_name = "$p_dir$dir_rel";
1092 $dir_pref = "$dir_name:";
1093 $loc_pref = ($dir_loc =~ /:$/) ? $dir_loc : "$dir_loc:";
1096 $dir_name = ($p_dir eq '/' ? "/$dir_rel" : "$p_dir/$dir_rel");
1097 $dir_pref = "$dir_name/";
1098 $loc_pref = "$dir_loc/";
1100 if ( $byd_flag < 0 ) { # must be finddepth, report dirname now
1101 unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
1102 unless (chdir $updir_loc) { # $updir_loc (parent dir) is always untainted
1103 warnings::warnif "Can't cd to $updir_loc: $!\n";
1107 $fullname = $dir_loc; # $File::Find::fullname
1108 $name = $dir_name; # $File::Find::name
1110 if ($dir_rel eq ':') { # must be the top dir, where we started
1111 $name =~ s|:$||; # $File::Find::name
1112 $p_dir = "$p_dir:" unless ($p_dir =~ /:$/);
1114 $dir = $p_dir; # $File::Find::dir
1115 $_ = ($no_chdir ? $name : $dir_rel); # $_
1118 if ( substr($name,-2) eq '/.' ) {
1119 substr($name, length($name) == 2 ? -1 : -2) = ''; # $File::Find::name
1121 $dir = $p_dir; # $File::Find::dir
1122 $_ = ($no_chdir ? $dir_name : $dir_rel); # $_
1123 if ( substr($_,-2) eq '/.' ) {
1124 substr($_, length($_) == 2 ? -1 : -2) = '';
1128 lstat($_); # make sure file tests with '_' work
1129 { $wanted_callback->() }; # protect against wild "next"
1132 push @Stack,[$dir_loc, $updir_loc, $p_dir, $dir_rel,-1] if $bydepth;
1142 if ( ref($wanted) eq 'HASH' ) {
1143 if ( $wanted->{follow} || $wanted->{follow_fast}) {
1144 $wanted->{follow_skip} = 1 unless defined $wanted->{follow_skip};
1146 if ( $wanted->{untaint} ) {
1147 $wanted->{untaint_pattern} = $File::Find::untaint_pattern
1148 unless defined $wanted->{untaint_pattern};
1149 $wanted->{untaint_skip} = 0 unless defined $wanted->{untaint_skip};
1154 return { wanted => $wanted };
1160 _find_opt(wrap_wanted($wanted), @_);
1164 my $wanted = wrap_wanted(shift);
1165 $wanted->{bydepth} = 1;
1166 _find_opt($wanted, @_);
1170 $File::Find::skip_pattern = qr/^\.{1,2}\z/;
1171 $File::Find::untaint_pattern = qr|^([-+@\w./]+)$|;
1173 # These are hard-coded for now, but may move to hint files.
1176 $File::Find::dont_use_nlink = 1;
1178 elsif ($^O eq 'MacOS') {
1180 $File::Find::dont_use_nlink = 1;
1181 $File::Find::skip_pattern = qr/^Icon\015\z/;
1182 $File::Find::untaint_pattern = qr|^(.+)$|;
1185 # this _should_ work properly on all platforms
1186 # where File::Find can be expected to work
1187 $File::Find::current_dir = File::Spec->curdir || '.';
1189 $File::Find::dont_use_nlink = 1
1190 if $^O eq 'os2' || $^O eq 'dos' || $^O eq 'amigaos' || $^O eq 'MSWin32' ||
1191 $^O eq 'cygwin' || $^O eq 'epoc' || $^O eq 'qnx' ||
1194 # Set dont_use_nlink in your hint file if your system's stat doesn't
1195 # report the number of links in a directory as an indication
1196 # of the number of files.
1197 # See, e.g. hints/machten.sh for MachTen 2.2.
1198 unless ($File::Find::dont_use_nlink) {
1200 $File::Find::dont_use_nlink = 1 if ($Config::Config{'dont_use_nlink'});
1203 # We need a function that checks if a scalar is tainted. Either use the
1204 # Scalar::Util module's tainted() function or our (slower) pure Perl
1205 # fallback is_tainted_pp()
1208 eval { require Scalar::Util };
1209 *is_tainted = $@ ? \&is_tainted_pp : \&Scalar::Util::tainted;