11 find - traverse a file tree
13 finddepth - traverse a directory structure depth-first
18 find(\&wanted, '/foo', '/bar');
22 finddepth(\&wanted, '/foo', '/bar');
26 find({ wanted => \&process, follow => 1 }, '.');
30 The first argument to find() is either a hash reference describing the
31 operations to be performed for each file, or a code reference.
33 Here are the possible keys for the hash:
39 The value should be a code reference. This code reference is called
40 I<the wanted() function> below.
44 Reports the name of a directory only AFTER all its entries
45 have been reported. Entry point finddepth() is a shortcut for
46 specifying C<{ bydepth => 1 }> in the first argument of find().
50 The value should be a code reference. This code reference is used to
51 preprocess the current directory. The name of currently processed
52 directory is in $File::Find::dir. Your preprocessing function is
53 called after readdir() but before the loop that calls the wanted()
54 function. It is called with a list of strings (actually file/directory
55 names) and is expected to return a list of strings. The code can be
56 used to sort the file/directory names alphabetically, numerically,
57 or to filter out directory entries based on their name alone. When
58 I<follow> or I<follow_fast> are in effect, C<preprocess> is a no-op.
62 The value should be a code reference. It is invoked just before leaving
63 the currently processed directory. It is called in void context with no
64 arguments. The name of the current directory is in $File::Find::dir. This
65 hook is handy for summarizing a directory, such as calculating its disk
66 usage. When I<follow> or I<follow_fast> are in effect, C<postprocess> is a
71 Causes symbolic links to be followed. Since directory trees with symbolic
72 links (followed) may contain files more than once and may even have
73 cycles, a hash has to be built up with an entry for each file.
74 This might be expensive both in space and time for a large
75 directory tree. See I<follow_fast> and I<follow_skip> below.
76 If either I<follow> or I<follow_fast> is in effect:
82 It is guaranteed that an I<lstat> has been called before the user's
83 I<wanted()> function is called. This enables fast file checks involving S< _>.
87 There is a variable C<$File::Find::fullname> which holds the absolute
88 pathname of the file with all symbolic links resolved
94 This is similar to I<follow> except that it may report some files more
95 than once. It does detect cycles, however. Since only symbolic links
96 have to be hashed, this is much cheaper both in space and time. If
97 processing a file more than once (by the user's I<wanted()> function)
98 is worse than just taking time, the option I<follow> should be used.
102 C<follow_skip==1>, which is the default, causes all files which are
103 neither directories nor symbolic links to be ignored if they are about
104 to be processed a second time. If a directory or a symbolic link
105 are about to be processed a second time, File::Find dies.
106 C<follow_skip==0> causes File::Find to die if any file is about to be
107 processed a second time.
108 C<follow_skip==2> causes File::Find to ignore any duplicate files and
109 directories but to proceed normally otherwise.
111 =item C<dangling_symlinks>
113 If true and a code reference, will be called with the symbolic link
114 name and the directory it lives in as arguments. Otherwise, if true
115 and warnings are on, warning "symbolic_link_name is a dangling
116 symbolic link\n" will be issued. If false, the dangling symbolic link
117 will be silently ignored.
121 Does not C<chdir()> to each directory as it recurses. The wanted()
122 function will need to be aware of this, of course. In this case,
123 C<$_> will be the same as C<$File::Find::name>.
127 If find is used in taint-mode (-T command line switch or if EUID != UID
128 or if EGID != GID) then internally directory names have to be untainted
129 before they can be chdir'ed to. Therefore they are checked against a regular
130 expression I<untaint_pattern>. Note that all names passed to the user's
131 I<wanted()> function are still tainted. If this option is used while
132 not in taint-mode, C<untaint> is a no-op.
134 =item C<untaint_pattern>
136 See above. This should be set using the C<qr> quoting operator.
137 The default is set to C<qr|^([-+@\w./]+)$|>.
138 Note that the parentheses are vital.
140 =item C<untaint_skip>
142 If set, a directory which fails the I<untaint_pattern> is skipped,
143 including all its sub-directories. The default is to 'die' in such a case.
147 The wanted() function does whatever verifications you want.
148 C<$File::Find::dir> contains the current directory name, and C<$_> the
149 current filename within that directory. C<$File::Find::name> contains
150 the complete pathname to the file. You are chdir()'d to
151 C<$File::Find::dir> when the function is called, unless C<no_chdir>
152 was specified. When C<follow> or C<follow_fast> are in effect, there is
153 also a C<$File::Find::fullname>. The function may set
154 C<$File::Find::prune> to prune the tree unless C<bydepth> was
155 specified. Unless C<follow> or C<follow_fast> is specified, for
156 compatibility reasons (find.pl, find2perl) there are in addition the
157 following globals available: C<$File::Find::topdir>,
158 C<$File::Find::topdev>, C<$File::Find::topino>,
159 C<$File::Find::topmode> and C<$File::Find::topnlink>.
161 This library is useful for the C<find2perl> tool, which when fed,
163 find2perl / -name .nfs\* -mtime +7 \
164 -exec rm -f {} \; -o -fstype nfs -prune
166 produces something like:
170 (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_)) &&
174 ($nlink || (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_))) &&
176 ($File::Find::prune = 1);
179 Notice the C<_> in the above C<int(-M _)>: the C<_> is a magical
180 filehandle that caches the information from the preceding
181 stat(), lstat(), or filetest.
183 Here's another interesting wanted function. It will find all symbolic
184 links that don't resolve:
187 -l && !-e && print "bogus link: $File::Find::name\n";
190 See also the script C<pfind> on CPAN for a nice application of this
197 =item $dont_use_nlink
199 You can set the variable C<$File::Find::dont_use_nlink> to 1, if you want to
200 force File::Find to always stat directories. This was used for systems
201 that do not have the correct C<nlink> count for directories. Examples are
202 ISO-9660 (CD-R), AFS, and operating systems like OS/2, DOS and a couple of
205 Since now File::Find should now detect such things on-the-fly and switch it
206 self to using stat, this will probably not a problem to you.
208 If you do set $dont_use_nlink to 1, you will notice slow-downs.
212 Be aware that the option to follow symbolic links can be dangerous.
213 Depending on the structure of the directory tree (including symbolic
214 links to directories) you might traverse a given (physical) directory
215 more than once (only if C<follow_fast> is in effect).
216 Furthermore, deleting or changing files in a symbolically linked directory
217 might cause very unpleasant surprises, since you delete or change files
218 in an unknown directory.
228 Mac OS (Classic) users should note a few differences:
234 The path separator is ':', not '/', and the current directory is denoted
235 as ':', not '.'. You should be careful about specifying relative pathnames.
236 While a full path always begins with a volume name, a relative pathname
237 should always begin with a ':'. If specifying a volume name only, a
238 trailing ':' is required.
242 C<$File::Find::dir> is guaranteed to end with a ':'. If C<$_>
243 contains the name of a directory, that name may or may not end with a
244 ':'. Likewise, C<$File::Find::name>, which contains the complete
245 pathname to that directory, and C<$File::Find::fullname>, which holds
246 the absolute pathname of that directory with all symbolic links resolved,
247 may or may not end with a ':'.
251 The default C<untaint_pattern> (see above) on Mac OS is set to
252 C<qr|^(.+)$|>. Note that the parentheses are vital.
256 The invisible system file "Icon\015" is ignored. While this file may
257 appear in every directory, there are some more invisible system files
258 on every volume, which are all located at the volume root level (i.e.
259 "MacintoshHD:"). These system files are B<not> excluded automatically.
260 Your filter may use the following code to recognize invisible files or
261 directories (requires Mac::Files):
265 # invisible() -- returns 1 if file/directory is invisible,
266 # 0 if it's visible or undef if an error occurred
270 my ($fileCat, $fileInfo);
271 my $invisible_flag = 1 << 14;
273 if ( $fileCat = FSpGetCatInfo($file) ) {
274 if ($fileInfo = $fileCat->ioFlFndrInfo() ) {
275 return (($fileInfo->fdFlags & $invisible_flag) && 1);
281 Generally, invisible files are system files, unless an odd application
282 decides to use invisible files for its own purposes. To distinguish
283 such files from system files, you have to look at the B<type> and B<creator>
284 file attributes. The MacPerl built-in functions C<GetFileInfo(FILE)> and
285 C<SetFileInfo(CREATOR, TYPE, FILES)> offer access to these attributes
286 (see MacPerl.pm for details).
288 Files that appear on the desktop actually reside in an (hidden) directory
289 named "Desktop Folder" on the particular disk volume. Note that, although
290 all desktop files appear to be on the same "virtual" desktop, each disk
291 volume actually maintains its own "Desktop Folder" directory.
299 File::Find used to produce incorrect results if called recursively.
300 During the development of perl 5.8 this bug was fixed.
301 The first fixed version of File::Find was 1.01.
305 our @ISA = qw(Exporter);
306 our @EXPORT = qw(find finddepth);
313 require File::Basename;
316 # Should ideally be my() not our() but local() currently
317 # refuses to operate on lexicals
320 our ($wanted_callback, $avoid_nlink, $bydepth, $no_chdir, $follow,
321 $follow_skip, $full_check, $untaint, $untaint_skip, $untaint_pat,
322 $pre_process, $post_process, $dangling_symlinks);
327 return substr($cdir,0,rindex($cdir,'/')) if $fn eq $File::Find::current_dir;
329 $cdir = substr($cdir,0,rindex($cdir,'/')+1);
333 my $abs_name= $cdir . $fn;
335 if (substr($fn,0,3) eq '../') {
336 1 while $abs_name =~ s!/[^/]*/\.\./!/!;
342 # return the absolute name of a directory or file
343 sub contract_name_Mac {
347 if ($fn =~ /^(:+)(.*)$/) { # valid pathname starting with a ':'
349 my $colon_count = length ($1);
350 if ($colon_count == 1) {
351 $abs_name = $cdir . $2;
355 # need to move up the tree, but
356 # only if it's not a volume name
357 for (my $i=1; $i<$colon_count; $i++) {
358 unless ($cdir =~ /^[^:]+:$/) { # volume name
359 $cdir =~ s/[^:]+:$//;
365 $abs_name = $cdir . $2;
372 # $fn may be a valid path to a directory or file or (dangling)
373 # symlink, without a leading ':'
374 if ( (-e $fn) || (-l $fn) ) {
375 if ($fn =~ /^[^:]+:/) { # a volume name like DataHD:*
376 return $fn; # $fn is already an absolute path
379 $abs_name = $cdir . $fn;
383 else { # argh!, $fn is not a valid directory/file
389 sub PathCombine($$) {
390 my ($Base,$Name) = @_;
394 # $Name is the resolved symlink (always a full path on MacOS),
395 # i.e. there's no need to call contract_name_Mac()
398 # (simple) check for recursion
399 if ( ( $Base =~ /^$AbsName/) && (-d $AbsName) ) { # recursion
404 if (substr($Name,0,1) eq '/') {
408 $AbsName= contract_name($Base,$Name);
411 # (simple) check for recursion
412 my $newlen= length($AbsName);
413 if ($newlen <= length($Base)) {
414 if (($newlen == length($Base) || substr($Base,$newlen,1) eq '/')
415 && $AbsName eq substr($Base,0,$newlen))
424 sub Follow_SymLink($) {
427 my ($NewName,$DEV, $INO);
428 ($DEV, $INO)= lstat $AbsName;
431 if ($SLnkSeen{$DEV, $INO}++) {
432 if ($follow_skip < 2) {
433 die "$AbsName is encountered a second time";
439 $NewName= PathCombine($AbsName, readlink($AbsName));
440 unless(defined $NewName) {
441 if ($follow_skip < 2) {
442 die "$AbsName is a recursive symbolic link";
451 ($DEV, $INO) = lstat($AbsName);
452 return undef unless defined $DEV; # dangling symbolic link
455 if ($full_check && $SLnkSeen{$DEV, $INO}++) {
456 if ( ($follow_skip < 1) || ((-d _) && ($follow_skip < 2)) ) {
457 die "$AbsName encountered a second time";
467 our($dir, $name, $fullname, $prune);
468 sub _find_dir_symlnk($$$);
471 # check whether or not a scalar variable is tainted
472 # (code straight from the Camel, 3rd ed., page 561)
475 my $nada = substr($arg, 0, 0); # zero-length
477 eval { eval "# $nada" };
478 return length($@) != 0;
483 die "invalid top directory" unless defined $_[0];
485 # This function must local()ize everything because callbacks may
486 # call find() or finddepth()
489 local ($wanted_callback, $avoid_nlink, $bydepth, $no_chdir, $follow,
490 $follow_skip, $full_check, $untaint, $untaint_skip, $untaint_pat,
491 $pre_process, $post_process, $dangling_symlinks);
492 local($dir, $name, $fullname, $prune);
494 my $cwd = $wanted->{bydepth} ? Cwd::fastcwd() : Cwd::getcwd();
495 my $cwd_untainted = $cwd;
497 $wanted_callback = $wanted->{wanted};
498 $bydepth = $wanted->{bydepth};
499 $pre_process = $wanted->{preprocess};
500 $post_process = $wanted->{postprocess};
501 $no_chdir = $wanted->{no_chdir};
502 $full_check = $wanted->{follow};
503 $follow = $full_check || $wanted->{follow_fast};
504 $follow_skip = $wanted->{follow_skip};
505 $untaint = $wanted->{untaint};
506 $untaint_pat = $wanted->{untaint_pattern};
507 $untaint_skip = $wanted->{untaint_skip};
508 $dangling_symlinks = $wanted->{dangling_symlinks};
510 # for compatibility reasons (find.pl, find2perl)
511 local our ($topdir, $topdev, $topino, $topmode, $topnlink);
513 # a symbolic link to a directory doesn't increase the link count
514 $avoid_nlink = $follow || $File::Find::dont_use_nlink;
516 my ($abs_dir, $Is_Dir);
519 foreach my $TOP (@_) {
523 ($topdev,$topino,$topmode,$topnlink) = $follow ? stat $top_item : lstat $top_item;
524 $top_item = ":$top_item"
525 if ( (-d _) && ( $top_item !~ /:/ ) );
528 $top_item =~ s|/\z|| unless $top_item eq '/';
529 ($topdev,$topino,$topmode,$topnlink) = $follow ? stat $top_item : lstat $top_item;
537 $cwd = "$cwd:" unless ($cwd =~ /:$/); # for safety
539 if ($top_item eq $File::Find::current_dir) {
543 $abs_dir = contract_name_Mac($cwd, $top_item);
544 unless (defined $abs_dir) {
545 warn "Can't determine absolute path for $top_item (No such file or directory)\n" if $^W;
552 if (substr($top_item,0,1) eq '/') {
553 $abs_dir = $top_item;
555 elsif ($top_item eq $File::Find::current_dir) {
558 else { # care about any ../
559 $abs_dir = contract_name("$cwd/",$top_item);
562 $abs_dir= Follow_SymLink($abs_dir);
563 unless (defined $abs_dir) {
564 if ($dangling_symlinks) {
565 if (ref $dangling_symlinks eq 'CODE') {
566 $dangling_symlinks->($top_item, $cwd);
568 warn "$top_item is a dangling symbolic link\n" if $^W;
575 _find_dir_symlnk($wanted, $abs_dir, $top_item);
581 unless (defined $topnlink) {
582 warn "Can't stat $top_item: $!\n" if $^W;
586 $top_item =~ s/\.dir\z// if $Is_VMS;
587 _find_dir($wanted, $top_item, $topnlink);
596 unless (($_,$dir) = File::Basename::fileparse($abs_dir)) {
598 ($dir,$_) = (':', $top_item); # $File::Find::dir, $_
601 ($dir,$_) = ('./', $top_item);
606 if (( $untaint ) && (is_tainted($dir) )) {
607 ( $abs_dir ) = $dir =~ m|$untaint_pat|;
608 unless (defined $abs_dir) {
609 if ($untaint_skip == 0) {
610 die "directory $dir is still tainted";
618 unless ($no_chdir || chdir $abs_dir) {
619 warn "Couldn't chdir $abs_dir: $!\n" if $^W;
623 $name = $abs_dir . $_; # $File::Find::name
625 { &$wanted_callback }; # protect against wild "next"
629 unless ( $no_chdir ) {
630 if ( ($check_t_cwd) && (($untaint) && (is_tainted($cwd) )) ) {
631 ( $cwd_untainted ) = $cwd =~ m|$untaint_pat|;
632 unless (defined $cwd_untainted) {
633 die "insecure cwd in find(depth)";
637 unless (chdir $cwd_untainted) {
638 die "Can't cd to $cwd: $!\n";
646 # $p_dir : "parent directory"
647 # $nlink : what came back from the stat
649 # chdir (if not no_chdir) to dir
652 my ($wanted, $p_dir, $nlink) = @_;
653 my ($CdLvl,$Level) = (0,0);
656 my ($subcount,$sub_nlink);
658 my $dir_name= $p_dir;
660 my $dir_rel = $File::Find::current_dir;
665 $dir_pref= ($p_dir =~ /:$/) ? $p_dir : "$p_dir:"; # preface
668 $dir_pref= ( $p_dir eq '/' ? '/' : "$p_dir/" );
671 local ($dir, $name, $prune, *DIR);
673 unless ( $no_chdir || ($p_dir eq $File::Find::current_dir)) {
675 if (( $untaint ) && (is_tainted($p_dir) )) {
676 ( $udir ) = $p_dir =~ m|$untaint_pat|;
677 unless (defined $udir) {
678 if ($untaint_skip == 0) {
679 die "directory $p_dir is still tainted";
686 unless (chdir $udir) {
687 warn "Can't cd to $udir: $!\n" if $^W;
692 # push the starting directory
693 push @Stack,[$CdLvl,$p_dir,$dir_rel,-1] if $bydepth;
696 $p_dir = $dir_pref; # ensure trailing ':'
699 while (defined $SE) {
701 $dir= $p_dir; # $File::Find::dir
702 $name= $dir_name; # $File::Find::name
703 $_= ($no_chdir ? $dir_name : $dir_rel ); # $_
704 # prune may happen here
706 { &$wanted_callback }; # protect against wild "next"
710 # change to that directory
711 unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
713 if ( ($untaint) && (($tainted) || ($tainted = is_tainted($dir_rel) )) ) {
714 ( $udir ) = $dir_rel =~ m|$untaint_pat|;
715 unless (defined $udir) {
716 if ($untaint_skip == 0) {
718 die "directory ($p_dir) $dir_rel is still tainted";
721 die "directory (" . ($p_dir ne '/' ? $p_dir : '') . "/) $dir_rel is still tainted";
723 } else { # $untaint_skip == 1
728 unless (chdir $udir) {
730 warn "Can't cd to ($p_dir) $udir: $!\n" if $^W;
733 warn "Can't cd to (" . ($p_dir ne '/' ? $p_dir : '') . "/) $udir: $!\n" if $^W;
741 $dir_name = "$dir_name:" unless ($dir_name =~ /:$/);
744 $dir= $dir_name; # $File::Find::dir
746 # Get the list of files in the current directory.
747 unless (opendir DIR, ($no_chdir ? $dir_name : $File::Find::current_dir)) {
748 warn "Can't opendir($dir_name): $!\n" if $^W;
751 @filenames = readdir DIR;
753 @filenames = &$pre_process(@filenames) if $pre_process;
754 push @Stack,[$CdLvl,$dir_name,"",-2] if $post_process;
756 # default: use whatever was specifid
757 # (if $nlink >= 2, and $avoid_nlink == 0, this will switch back)
758 $no_nlink = $avoid_nlink;
759 # if dir has wrong nlink count, force switch to slower stat method
760 $no_nlink = 1 if ($nlink < 2);
762 if ($nlink == 2 && !$no_nlink) {
763 # This dir has no subdirectories.
764 for my $FN (@filenames) {
765 next if $FN =~ $File::Find::skip_pattern;
767 $name = $dir_pref . $FN; # $File::Find::name
768 $_ = ($no_chdir ? $name : $FN); # $_
769 { &$wanted_callback }; # protect against wild "next"
774 # This dir has subdirectories.
775 $subcount = $nlink - 2;
777 for my $FN (@filenames) {
778 next if $FN =~ $File::Find::skip_pattern;
779 if ($subcount > 0 || $no_nlink) {
780 # Seen all the subdirs?
781 # check for directoriness.
782 # stat is faster for a file in the current directory
783 $sub_nlink = (lstat ($no_chdir ? $dir_pref . $FN : $FN))[3];
787 $FN =~ s/\.dir\z// if $Is_VMS;
788 push @Stack,[$CdLvl,$dir_name,$FN,$sub_nlink];
791 $name = $dir_pref . $FN; # $File::Find::name
792 $_= ($no_chdir ? $name : $FN); # $_
793 { &$wanted_callback }; # protect against wild "next"
797 $name = $dir_pref . $FN; # $File::Find::name
798 $_= ($no_chdir ? $name : $FN); # $_
799 { &$wanted_callback }; # protect against wild "next"
805 while ( defined ($SE = pop @Stack) ) {
806 ($Level, $p_dir, $dir_rel, $nlink) = @$SE;
807 if ($CdLvl > $Level && !$no_chdir) {
810 $tmp = (':' x ($CdLvl-$Level)) . ':';
813 $tmp = join('/',('..') x ($CdLvl-$Level));
815 die "Can't cd to $dir_name" . $tmp
821 # $pdir always has a trailing ':', except for the starting dir,
822 # where $dir_rel eq ':'
823 $dir_name = "$p_dir$dir_rel";
824 $dir_pref = "$dir_name:";
827 $dir_name = ($p_dir eq '/' ? "/$dir_rel" : "$p_dir/$dir_rel");
828 $dir_pref = "$dir_name/";
831 if ( $nlink == -2 ) {
832 $name = $dir = $p_dir; # $File::Find::name / dir
833 $_ = $File::Find::current_dir;
834 &$post_process; # End-of-directory processing
836 elsif ( $nlink < 0 ) { # must be finddepth, report dirname now
839 if ($dir_rel eq ':') { # must be the top dir, where we started
840 $name =~ s|:$||; # $File::Find::name
841 $p_dir = "$p_dir:" unless ($p_dir =~ /:$/);
843 $dir = $p_dir; # $File::Find::dir
844 $_ = ($no_chdir ? $name : $dir_rel); # $_
847 if ( substr($name,-2) eq '/.' ) {
851 $_ = ($no_chdir ? $dir_name : $dir_rel );
852 if ( substr($_,-2) eq '/.' ) {
856 { &$wanted_callback }; # protect against wild "next"
859 push @Stack,[$CdLvl,$p_dir,$dir_rel,-1] if $bydepth;
869 # $dir_loc : absolute location of a dir
870 # $p_dir : "parent directory"
872 # chdir (if not no_chdir) to dir
874 sub _find_dir_symlnk($$$) {
875 my ($wanted, $dir_loc, $p_dir) = @_; # $dir_loc is the absolute directory
879 my $updir_loc = $dir_loc; # untainted parent directory
881 my $dir_name = $p_dir;
884 my $dir_rel = $File::Find::current_dir;
885 my $byd_flag; # flag for pending stack entry if $bydepth
890 $dir_pref = ($p_dir =~ /:$/) ? "$p_dir" : "$p_dir:";
891 $loc_pref = ($dir_loc =~ /:$/) ? "$dir_loc" : "$dir_loc:";
893 $dir_pref = ( $p_dir eq '/' ? '/' : "$p_dir/" );
894 $loc_pref = ( $dir_loc eq '/' ? '/' : "$dir_loc/" );
897 local ($dir, $name, $fullname, $prune, *DIR);
901 if (( $untaint ) && (is_tainted($dir_loc) )) {
902 ( $updir_loc ) = $dir_loc =~ m|$untaint_pat|; # parent dir, now untainted
903 # once untainted, $updir_loc is pushed on the stack (as parent directory);
904 # hence, we don't need to untaint the parent directory every time we chdir
906 unless (defined $updir_loc) {
907 if ($untaint_skip == 0) {
908 die "directory $dir_loc is still tainted";
915 $ok = chdir($updir_loc) unless ($p_dir eq $File::Find::current_dir);
917 warn "Can't cd to $updir_loc: $!\n" if $^W;
922 push @Stack,[$dir_loc,$updir_loc,$p_dir,$dir_rel,-1] if $bydepth;
925 $p_dir = $dir_pref; # ensure trailing ':'
928 while (defined $SE) {
931 # change (back) to parent directory (always untainted)
933 unless (chdir $updir_loc) {
934 warn "Can't cd to $updir_loc: $!\n" if $^W;
938 $dir= $p_dir; # $File::Find::dir
939 $name= $dir_name; # $File::Find::name
940 $_= ($no_chdir ? $dir_name : $dir_rel ); # $_
941 $fullname= $dir_loc; # $File::Find::fullname
942 # prune may happen here
944 lstat($_); # make sure file tests with '_' work
945 { &$wanted_callback }; # protect against wild "next"
949 # change to that directory
950 unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
951 $updir_loc = $dir_loc;
952 if ( ($untaint) && (($tainted) || ($tainted = is_tainted($dir_loc) )) ) {
953 # untaint $dir_loc, what will be pushed on the stack as (untainted) parent dir
954 ( $updir_loc ) = $dir_loc =~ m|$untaint_pat|;
955 unless (defined $updir_loc) {
956 if ($untaint_skip == 0) {
957 die "directory $dir_loc is still tainted";
964 unless (chdir $updir_loc) {
965 warn "Can't cd to $updir_loc: $!\n" if $^W;
971 $dir_name = "$dir_name:" unless ($dir_name =~ /:$/);
974 $dir = $dir_name; # $File::Find::dir
976 # Get the list of files in the current directory.
977 unless (opendir DIR, ($no_chdir ? $dir_loc : $File::Find::current_dir)) {
978 warn "Can't opendir($dir_loc): $!\n" if $^W;
981 @filenames = readdir DIR;
984 for my $FN (@filenames) {
985 next if $FN =~ $File::Find::skip_pattern;
987 # follow symbolic links / do an lstat
988 $new_loc = Follow_SymLink($loc_pref.$FN);
990 # ignore if invalid symlink
991 next unless defined $new_loc;
994 push @Stack,[$new_loc,$updir_loc,$dir_name,$FN,1];
997 $fullname = $new_loc; # $File::Find::fullname
998 $name = $dir_pref . $FN; # $File::Find::name
999 $_ = ($no_chdir ? $name : $FN); # $_
1000 { &$wanted_callback }; # protect against wild "next"
1006 while (defined($SE = pop @Stack)) {
1007 ($dir_loc, $updir_loc, $p_dir, $dir_rel, $byd_flag) = @$SE;
1009 # $p_dir always has a trailing ':', except for the starting dir,
1010 # where $dir_rel eq ':'
1011 $dir_name = "$p_dir$dir_rel";
1012 $dir_pref = "$dir_name:";
1013 $loc_pref = ($dir_loc =~ /:$/) ? $dir_loc : "$dir_loc:";
1016 $dir_name = ($p_dir eq '/' ? "/$dir_rel" : "$p_dir/$dir_rel");
1017 $dir_pref = "$dir_name/";
1018 $loc_pref = "$dir_loc/";
1020 if ( $byd_flag < 0 ) { # must be finddepth, report dirname now
1021 unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
1022 unless (chdir $updir_loc) { # $updir_loc (parent dir) is always untainted
1023 warn "Can't cd to $updir_loc: $!\n" if $^W;
1027 $fullname = $dir_loc; # $File::Find::fullname
1028 $name = $dir_name; # $File::Find::name
1030 if ($dir_rel eq ':') { # must be the top dir, where we started
1031 $name =~ s|:$||; # $File::Find::name
1032 $p_dir = "$p_dir:" unless ($p_dir =~ /:$/);
1034 $dir = $p_dir; # $File::Find::dir
1035 $_ = ($no_chdir ? $name : $dir_rel); # $_
1038 if ( substr($name,-2) eq '/.' ) {
1039 $name =~ s|/\.$||; # $File::Find::name
1041 $dir = $p_dir; # $File::Find::dir
1042 $_ = ($no_chdir ? $dir_name : $dir_rel); # $_
1043 if ( substr($_,-2) eq '/.' ) {
1048 lstat($_); # make sure file tests with '_' work
1049 { &$wanted_callback }; # protect against wild "next"
1052 push @Stack,[$dir_loc, $updir_loc, $p_dir, $dir_rel,-1] if $bydepth;
1062 if ( ref($wanted) eq 'HASH' ) {
1063 if ( $wanted->{follow} || $wanted->{follow_fast}) {
1064 $wanted->{follow_skip} = 1 unless defined $wanted->{follow_skip};
1066 if ( $wanted->{untaint} ) {
1067 $wanted->{untaint_pattern} = $File::Find::untaint_pattern
1068 unless defined $wanted->{untaint_pattern};
1069 $wanted->{untaint_skip} = 0 unless defined $wanted->{untaint_skip};
1074 return { wanted => $wanted };
1080 _find_opt(wrap_wanted($wanted), @_);
1084 my $wanted = wrap_wanted(shift);
1085 $wanted->{bydepth} = 1;
1086 _find_opt($wanted, @_);
1090 $File::Find::skip_pattern = qr/^\.{1,2}\z/;
1091 $File::Find::untaint_pattern = qr|^([-+@\w./]+)$|;
1093 # These are hard-coded for now, but may move to hint files.
1096 $File::Find::dont_use_nlink = 1;
1098 elsif ($^O eq 'MacOS') {
1100 $File::Find::dont_use_nlink = 1;
1101 $File::Find::skip_pattern = qr/^Icon\015\z/;
1102 $File::Find::untaint_pattern = qr|^(.+)$|;
1105 # this _should_ work properly on all platforms
1106 # where File::Find can be expected to work
1107 $File::Find::current_dir = File::Spec->curdir || '.';
1109 $File::Find::dont_use_nlink = 1
1110 if $^O eq 'os2' || $^O eq 'dos' || $^O eq 'amigaos' || $^O eq 'MSWin32' ||
1111 $^O eq 'cygwin' || $^O eq 'epoc' || $^O eq 'NetWare';
1113 # Set dont_use_nlink in your hint file if your system's stat doesn't
1114 # report the number of links in a directory as an indication
1115 # of the number of files.
1116 # See, e.g. hints/machten.sh for MachTen 2.2.
1117 unless ($File::Find::dont_use_nlink) {
1119 $File::Find::dont_use_nlink = 1 if ($Config::Config{'dont_use_nlink'});
1122 # We need a function that checks if a scalar is tainted. Either use the
1123 # Scalar::Util module's tainted() function or our (slower) pure Perl
1124 # fallback is_tainted_pp()
1127 eval { require Scalar::Util };
1128 *is_tainted = $@ ? \&is_tainted_pp : \&Scalar::Util::tainted;