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<preprocess> 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.
114 Does not C<chdir()> to each directory as it recurses. The wanted()
115 function will need to be aware of this, of course. In this case,
116 C<$_> will be the same as C<$File::Find::name>.
120 If find is used in taint-mode (-T command line switch or if EUID != UID
121 or if EGID != GID) then internally directory names have to be untainted
122 before they can be chdir'ed to. Therefore they are checked against a regular
123 expression I<untaint_pattern>. Note that all names passed to the user's
124 I<wanted()> function are still tainted. If this option is used while
125 not in taint-mode, C<untaint> is a no-op.
127 =item C<untaint_pattern>
129 See above. This should be set using the C<qr> quoting operator.
130 The default is set to C<qr|^([-+@\w./]+)$|>.
131 Note that the parantheses are vital.
133 =item C<untaint_skip>
135 If set, a directory which fails the I<untaint_pattern> is skipped,
136 including all its sub-directories. The default is to 'die' in such a case.
140 The wanted() function does whatever verifications you want.
141 C<$File::Find::dir> contains the current directory name, and C<$_> the
142 current filename within that directory. C<$File::Find::name> contains
143 the complete pathname to the file. You are chdir()'d to
144 C<$File::Find::dir> when the function is called, unless C<no_chdir>
145 was specified. When C<follow> or C<follow_fast> are in effect, there is
146 also a C<$File::Find::fullname>. The function may set
147 C<$File::Find::prune> to prune the tree unless C<bydepth> was
148 specified. Unless C<follow> or C<follow_fast> is specified, for
149 compatibility reasons (find.pl, find2perl) there are in addition the
150 following globals available: C<$File::Find::topdir>,
151 C<$File::Find::topdev>, C<$File::Find::topino>,
152 C<$File::Find::topmode> and C<$File::Find::topnlink>.
154 This library is useful for the C<find2perl> tool, which when fed,
156 find2perl / -name .nfs\* -mtime +7 \
157 -exec rm -f {} \; -o -fstype nfs -prune
159 produces something like:
163 (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_)) &&
167 ($nlink || (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_))) &&
169 ($File::Find::prune = 1);
172 Set the variable C<$File::Find::dont_use_nlink> if you're using AFS,
176 Here's another interesting wanted function. It will find all symlinks
180 -l && !-e && print "bogus link: $File::Find::name\n";
183 See also the script C<pfind> on CPAN for a nice application of this
188 Be aware that the option to follow symbolic links can be dangerous.
189 Depending on the structure of the directory tree (including symbolic
190 links to directories) you might traverse a given (physical) directory
191 more than once (only if C<follow_fast> is in effect).
192 Furthermore, deleting or changing files in a symbolically linked directory
193 might cause very unpleasant surprises, since you delete or change files
194 in an unknown directory.
202 Mac OS (Classic) users should note a few differences:
208 The path separator is ':', not '/', and the current directory is denoted
209 as ':', not '.'. You should be careful about specifying relative pathnames.
210 While a full path always begins with a volume name, a relative pathname
211 should always begin with a ':'. If specifying a volume name only, a
212 trailing ':' is required.
216 C<$File::Find::dir> is guaranteed to end with a ':'. If C<$_>
217 contains the name of a directory, that name may or may not end with a
218 ':'. Likewise, C<$File::Find::name>, which contains the complete
219 pathname to that directory, and C<$File::Find::fullname>, which holds
220 the absolute pathname of that directory with all symbolic links resolved,
221 may or may not end with a ':'.
225 The default C<untaint_pattern> (see above) on Mac OS is set to
226 C<qr|^(.+)$|>. Note that the parentheses are vital.
230 The invisible system file "Icon\015" is ignored. While this file may
231 appear in every directory, there are some more invisible system files
232 on every volume, which are all located at the volume root level (i.e.
233 "MacintoshHD:"). These system files are B<not> excluded automatically.
234 Your filter may use the following code to recognize invisible files or
235 directories (requires Mac::Files):
239 # invisible() -- returns 1 if file/directory is invisible,
240 # 0 if it's visible or undef if an error occured
244 my ($fileCat, $fileInfo);
245 my $invisible_flag = 1 << 14;
247 if ( $fileCat = FSpGetCatInfo($file) ) {
248 if ($fileInfo = $fileCat->ioFlFndrInfo() ) {
249 return (($fileInfo->fdFlags & $invisible_flag) && 1);
255 Generally, invisible files are system files, unless an odd application
256 decides to use invisible files for its own purposes. To distinguish
257 such files from system files, you have to look at the B<type> and B<creator>
258 file attributes. The MacPerl built-in functions C<GetFileInfo(FILE)> and
259 C<SetFileInfo(CREATOR, TYPE, FILES)> offer access to these attributes
260 (see MacPerl.pm for details).
262 Files that appear on the desktop actually reside in an (hidden) directory
263 named "Desktop Folder" on the particular disk volume. Note that, although
264 all desktop files appear to be on the same "virtual" desktop, each disk
265 volume actually maintains its own "Desktop Folder" directory.
273 our @ISA = qw(Exporter);
274 our @EXPORT = qw(find finddepth);
281 require File::Basename;
284 # Should ideally be my() not our() but local() currently
285 # refuses to operate on lexicals
288 our ($wanted_callback, $avoid_nlink, $bydepth, $no_chdir, $follow,
289 $follow_skip, $full_check, $untaint, $untaint_skip, $untaint_pat,
290 $pre_process, $post_process);
295 return substr($cdir,0,rindex($cdir,'/')) if $fn eq $File::Find::current_dir;
297 $cdir = substr($cdir,0,rindex($cdir,'/')+1);
301 my $abs_name= $cdir . $fn;
303 if (substr($fn,0,3) eq '../') {
304 1 while $abs_name =~ s!/[^/]*/\.\./!/!;
310 # return the absolute name of a directory or file
311 sub contract_name_Mac {
315 if ($fn =~ /^(:+)(.*)$/) { # valid pathname starting with a ':'
317 my $colon_count = length ($1);
318 if ($colon_count == 1) {
319 $abs_name = $cdir . $2;
323 # need to move up the tree, but
324 # only if it's not a volume name
325 for (my $i=1; $i<$colon_count; $i++) {
326 unless ($cdir =~ /^[^:]+:$/) { # volume name
327 $cdir =~ s/[^:]+:$//;
333 $abs_name = $cdir . $2;
340 # $fn may be a valid path to a directory or file or (dangling)
341 # symlink, without a leading ':'
342 if ( (-e $fn) || (-l $fn) ) {
343 if ($fn =~ /^[^:]+:/) { # a volume name like DataHD:*
344 return $fn; # $fn is already an absolute path
347 $abs_name = $cdir . $fn;
351 else { # argh!, $fn is not a valid directory/file
357 sub PathCombine($$) {
358 my ($Base,$Name) = @_;
362 # $Name is the resolved symlink (always a full path on MacOS),
363 # i.e. there's no need to call contract_name_Mac()
366 # (simple) check for recursion
367 if ( ( $Base =~ /^$AbsName/) && (-d $AbsName) ) { # recursion
372 if (substr($Name,0,1) eq '/') {
376 $AbsName= contract_name($Base,$Name);
379 # (simple) check for recursion
380 my $newlen= length($AbsName);
381 if ($newlen <= length($Base)) {
382 if (($newlen == length($Base) || substr($Base,$newlen,1) eq '/')
383 && $AbsName eq substr($Base,0,$newlen))
392 sub Follow_SymLink($) {
395 my ($NewName,$DEV, $INO);
396 ($DEV, $INO)= lstat $AbsName;
399 if ($SLnkSeen{$DEV, $INO}++) {
400 if ($follow_skip < 2) {
401 die "$AbsName is encountered a second time";
407 $NewName= PathCombine($AbsName, readlink($AbsName));
408 unless(defined $NewName) {
409 if ($follow_skip < 2) {
410 die "$AbsName is a recursive symbolic link";
419 ($DEV, $INO) = lstat($AbsName);
420 return undef unless defined $DEV; # dangling symbolic link
423 if ($full_check && $SLnkSeen{$DEV, $INO}++) {
424 if ( ($follow_skip < 1) || ((-d _) && ($follow_skip < 2)) ) {
425 die "$AbsName encountered a second time";
435 our($dir, $name, $fullname, $prune);
436 sub _find_dir_symlnk($$$);
439 # check whether or not a scalar variable is tainted
440 # (code straight from the Camel, 3rd ed., page 561)
443 my $nada = substr($arg, 0, 0); # zero-length
445 eval { eval "# $nada" };
446 return length($@) != 0;
451 die "invalid top directory" unless defined $_[0];
453 # This function must local()ize everything because callbacks may
454 # call find() or finddepth()
457 local ($wanted_callback, $avoid_nlink, $bydepth, $no_chdir, $follow,
458 $follow_skip, $full_check, $untaint, $untaint_skip, $untaint_pat,
459 $pre_process, $post_process);
460 local($dir, $name, $fullname, $prune);
462 my $cwd = $wanted->{bydepth} ? Cwd::fastcwd() : Cwd::cwd();
463 my $cwd_untainted = $cwd;
465 $wanted_callback = $wanted->{wanted};
466 $bydepth = $wanted->{bydepth};
467 $pre_process = $wanted->{preprocess};
468 $post_process = $wanted->{postprocess};
469 $no_chdir = $wanted->{no_chdir};
470 $full_check = $wanted->{follow};
471 $follow = $full_check || $wanted->{follow_fast};
472 $follow_skip = $wanted->{follow_skip};
473 $untaint = $wanted->{untaint};
474 $untaint_pat = $wanted->{untaint_pattern};
475 $untaint_skip = $wanted->{untaint_skip};
477 # for compatability reasons (find.pl, find2perl)
478 local our ($topdir, $topdev, $topino, $topmode, $topnlink);
480 # a symbolic link to a directory doesn't increase the link count
481 $avoid_nlink = $follow || $File::Find::dont_use_nlink;
483 my ($abs_dir, $Is_Dir);
486 foreach my $TOP (@_) {
490 ($topdev,$topino,$topmode,$topnlink) = $follow ? stat $top_item : lstat $top_item;
491 $top_item = ":$top_item"
492 if ( (-d _) && ($top_item =~ /^[^:]+\z/) );
495 $top_item =~ s|/\z|| unless $top_item eq '/';
496 ($topdev,$topino,$topmode,$topnlink) = $follow ? stat $top_item : lstat $top_item;
504 $cwd = "$cwd:" unless ($cwd =~ /:$/); # for safety
506 if ($top_item eq $File::Find::current_dir) {
510 $abs_dir = contract_name_Mac($cwd, $top_item);
511 unless (defined $abs_dir) {
512 warn "Can't determine absolute path for $top_item (No such file or directory)\n";
519 if (substr($top_item,0,1) eq '/') {
520 $abs_dir = $top_item;
522 elsif ($top_item eq $File::Find::current_dir) {
525 else { # care about any ../
526 $abs_dir = contract_name("$cwd/",$top_item);
529 $abs_dir= Follow_SymLink($abs_dir);
530 unless (defined $abs_dir) {
531 warn "$top_item is a dangling symbolic link\n";
536 _find_dir_symlnk($wanted, $abs_dir, $top_item);
542 unless (defined $topnlink) {
543 warn "Can't stat $top_item: $!\n";
547 $top_item =~ s/\.dir\z// if $Is_VMS;
548 _find_dir($wanted, $top_item, $topnlink);
557 unless (($_,$dir) = File::Basename::fileparse($abs_dir)) {
559 ($dir,$_) = (':', $top_item); # $File::Find::dir, $_
562 ($dir,$_) = ('./', $top_item);
567 if (( $untaint ) && (is_tainted($dir) )) {
568 ( $abs_dir ) = $dir =~ m|$untaint_pat|;
569 unless (defined $abs_dir) {
570 if ($untaint_skip == 0) {
571 die "directory $dir is still tainted";
579 unless ($no_chdir || chdir $abs_dir) {
580 warn "Couldn't chdir $abs_dir: $!\n";
584 $name = $abs_dir . $_; # $File::Find::name
586 { &$wanted_callback }; # protect against wild "next"
590 unless ( $no_chdir ) {
591 if ( ($check_t_cwd) && (($untaint) && (is_tainted($cwd) )) ) {
592 ( $cwd_untainted ) = $cwd =~ m|$untaint_pat|;
593 unless (defined $cwd_untainted) {
594 die "insecure cwd in find(depth)";
598 unless (chdir $cwd_untainted) {
599 die "Can't cd to $cwd: $!\n";
607 # $p_dir : "parent directory"
608 # $nlink : what came back from the stat
610 # chdir (if not no_chdir) to dir
613 my ($wanted, $p_dir, $nlink) = @_;
614 my ($CdLvl,$Level) = (0,0);
617 my ($subcount,$sub_nlink);
619 my $dir_name= $p_dir;
625 $dir_pref= ($p_dir =~ /:$/) ? $p_dir : "$p_dir:"; # preface
626 $dir_rel= ':'; # directory name relative to current directory
629 $dir_pref= ( $p_dir eq '/' ? '/' : "$p_dir/" );
630 $dir_rel= '.'; # directory name relative to current directory
633 local ($dir, $name, $prune, *DIR);
635 unless ( $no_chdir || ($p_dir eq $File::Find::current_dir)) {
637 if (( $untaint ) && (is_tainted($p_dir) )) {
638 ( $udir ) = $p_dir =~ m|$untaint_pat|;
639 unless (defined $udir) {
640 if ($untaint_skip == 0) {
641 die "directory $p_dir is still tainted";
648 unless (chdir $udir) {
649 warn "Can't cd to $udir: $!\n";
654 # push the starting directory
655 push @Stack,[$CdLvl,$p_dir,$dir_rel,-1] if $bydepth;
658 $p_dir = $dir_pref; # ensure trailing ':'
661 while (defined $SE) {
663 $dir= $p_dir; # $File::Find::dir
664 $name= $dir_name; # $File::Find::name
665 $_= ($no_chdir ? $dir_name : $dir_rel ); # $_
666 # prune may happen here
668 { &$wanted_callback }; # protect against wild "next"
672 # change to that directory
673 unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
675 if ( ($untaint) && (($tainted) || ($tainted = is_tainted($dir_rel) )) ) {
676 ( $udir ) = $dir_rel =~ m|$untaint_pat|;
677 unless (defined $udir) {
678 if ($untaint_skip == 0) {
680 die "directory ($p_dir) $dir_rel is still tainted";
683 die "directory (" . ($p_dir ne '/' ? $p_dir : '') . "/) $dir_rel is still tainted";
685 } else { # $untaint_skip == 1
690 unless (chdir $udir) {
692 warn "Can't cd to ($p_dir) $udir: $!\n";
695 warn "Can't cd to (" . ($p_dir ne '/' ? $p_dir : '') . "/) $udir: $!\n";
703 $dir_name = "$dir_name:" unless ($dir_name =~ /:$/);
706 $dir= $dir_name; # $File::Find::dir
708 # Get the list of files in the current directory.
709 unless (opendir DIR, ($no_chdir ? $dir_name : $File::Find::current_dir)) {
710 warn "Can't opendir($dir_name): $!\n";
713 @filenames = readdir DIR;
715 @filenames = &$pre_process(@filenames) if $pre_process;
716 push @Stack,[$CdLvl,$dir_name,"",-2] if $post_process;
718 if ($nlink == 2 && !$avoid_nlink) {
719 # This dir has no subdirectories.
720 for my $FN (@filenames) {
721 next if $FN =~ $File::Find::skip_pattern;
723 $name = $dir_pref . $FN; # $File::Find::name
724 $_ = ($no_chdir ? $name : $FN); # $_
725 { &$wanted_callback }; # protect against wild "next"
730 # This dir has subdirectories.
731 $subcount = $nlink - 2;
733 for my $FN (@filenames) {
734 next if $FN =~ $File::Find::skip_pattern;
735 if ($subcount > 0 || $avoid_nlink) {
736 # Seen all the subdirs?
737 # check for directoriness.
738 # stat is faster for a file in the current directory
739 $sub_nlink = (lstat ($no_chdir ? $dir_pref . $FN : $FN))[3];
743 $FN =~ s/\.dir\z// if $Is_VMS;
744 push @Stack,[$CdLvl,$dir_name,$FN,$sub_nlink];
747 $name = $dir_pref . $FN; # $File::Find::name
748 $_= ($no_chdir ? $name : $FN); # $_
749 { &$wanted_callback }; # protect against wild "next"
753 $name = $dir_pref . $FN; # $File::Find::name
754 $_= ($no_chdir ? $name : $FN); # $_
755 { &$wanted_callback }; # protect against wild "next"
761 while ( defined ($SE = pop @Stack) ) {
762 ($Level, $p_dir, $dir_rel, $nlink) = @$SE;
763 if ($CdLvl > $Level && !$no_chdir) {
766 $tmp = (':' x ($CdLvl-$Level)) . ':';
769 $tmp = join('/',('..') x ($CdLvl-$Level));
771 die "Can't cd to $dir_name" . $tmp
777 # $pdir always has a trailing ':', except for the starting dir,
778 # where $dir_rel eq ':'
779 $dir_name = "$p_dir$dir_rel";
780 $dir_pref = "$dir_name:";
783 $dir_name = ($p_dir eq '/' ? "/$dir_rel" : "$p_dir/$dir_rel");
784 $dir_pref = "$dir_name/";
787 if ( $nlink == -2 ) {
788 $name = $dir = $p_dir; # $File::Find::name / dir
795 &$post_process; # End-of-directory processing
797 elsif ( $nlink < 0 ) { # must be finddepth, report dirname now
800 if ($dir_rel eq ':') { # must be the top dir, where we started
801 $name =~ s|:$||; # $File::Find::name
802 $p_dir = "$p_dir:" unless ($p_dir =~ /:$/);
804 $dir = $p_dir; # $File::Find::dir
805 $_ = ($no_chdir ? $name : $dir_rel); # $_
808 if ( substr($name,-2) eq '/.' ) {
812 $_ = ($no_chdir ? $dir_name : $dir_rel );
813 if ( substr($_,-2) eq '/.' ) {
817 { &$wanted_callback }; # protect against wild "next"
820 push @Stack,[$CdLvl,$p_dir,$dir_rel,-1] if $bydepth;
830 # $dir_loc : absolute location of a dir
831 # $p_dir : "parent directory"
833 # chdir (if not no_chdir) to dir
835 sub _find_dir_symlnk($$$) {
836 my ($wanted, $dir_loc, $p_dir) = @_; # $dir_loc is the absolute directory
840 my $updir_loc = $dir_loc; # untainted parent directory
842 my $dir_name = $p_dir;
846 my $byd_flag; # flag for pending stack entry if $bydepth
851 $dir_pref = ($p_dir =~ /:$/) ? "$p_dir" : "$p_dir:";
852 $loc_pref = ($dir_loc =~ /:$/) ? "$dir_loc" : "$dir_loc:";
853 $dir_rel = ':'; # directory name relative to current directory
855 $dir_pref = ( $p_dir eq '/' ? '/' : "$p_dir/" );
856 $loc_pref = ( $dir_loc eq '/' ? '/' : "$dir_loc/" );
857 $dir_rel = '.'; # directory name relative to current directory
860 local ($dir, $name, $fullname, $prune, *DIR);
864 if (( $untaint ) && (is_tainted($dir_loc) )) {
865 ( $updir_loc ) = $dir_loc =~ m|$untaint_pat|; # parent dir, now untainted
866 # once untainted, $updir_loc is pushed on the stack (as parent directory);
867 # hence, we don't need to untaint the parent directory every time we chdir
869 unless (defined $updir_loc) {
870 if ($untaint_skip == 0) {
871 die "directory $dir_loc is still tainted";
878 $ok = chdir($updir_loc) unless ($p_dir eq $File::Find::current_dir);
880 warn "Can't cd to $updir_loc: $!\n";
885 push @Stack,[$dir_loc,$updir_loc,$p_dir,$dir_rel,-1] if $bydepth;
888 $p_dir = $dir_pref; # ensure trailing ':'
891 while (defined $SE) {
894 # change (back) to parent directory (always untainted)
896 unless (chdir $updir_loc) {
897 warn "Can't cd to $updir_loc: $!\n";
901 $dir= $p_dir; # $File::Find::dir
902 $name= $dir_name; # $File::Find::name
903 $_= ($no_chdir ? $dir_name : $dir_rel ); # $_
904 $fullname= $dir_loc; # $File::Find::fullname
905 # prune may happen here
907 lstat($_); # make sure file tests with '_' work
908 { &$wanted_callback }; # protect against wild "next"
912 # change to that directory
913 unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
914 $updir_loc = $dir_loc;
915 if ( ($untaint) && (($tainted) || ($tainted = is_tainted($dir_loc) )) ) {
916 # untaint $dir_loc, what will be pushed on the stack as (untainted) parent dir
917 ( $updir_loc ) = $dir_loc =~ m|$untaint_pat|;
918 unless (defined $updir_loc) {
919 if ($untaint_skip == 0) {
920 die "directory $dir_loc is still tainted";
927 unless (chdir $updir_loc) {
928 warn "Can't cd to $updir_loc: $!\n";
934 $dir_name = "$dir_name:" unless ($dir_name =~ /:$/);
937 $dir = $dir_name; # $File::Find::dir
939 # Get the list of files in the current directory.
940 unless (opendir DIR, ($no_chdir ? $dir_loc : $File::Find::current_dir)) {
941 warn "Can't opendir($dir_loc): $!\n";
944 @filenames = readdir DIR;
947 for my $FN (@filenames) {
948 next if $FN =~ $File::Find::skip_pattern;
950 # follow symbolic links / do an lstat
951 $new_loc = Follow_SymLink($loc_pref.$FN);
953 # ignore if invalid symlink
954 next unless defined $new_loc;
957 push @Stack,[$new_loc,$updir_loc,$dir_name,$FN,1];
960 $fullname = $new_loc; # $File::Find::fullname
961 $name = $dir_pref . $FN; # $File::Find::name
962 $_ = ($no_chdir ? $name : $FN); # $_
963 { &$wanted_callback }; # protect against wild "next"
969 while (defined($SE = pop @Stack)) {
970 ($dir_loc, $updir_loc, $p_dir, $dir_rel, $byd_flag) = @$SE;
972 # $p_dir always has a trailing ':', except for the starting dir,
973 # where $dir_rel eq ':'
974 $dir_name = "$p_dir$dir_rel";
975 $dir_pref = "$dir_name:";
976 $loc_pref = ($dir_loc =~ /:$/) ? $dir_loc : "$dir_loc:";
979 $dir_name = ($p_dir eq '/' ? "/$dir_rel" : "$p_dir/$dir_rel");
980 $dir_pref = "$dir_name/";
981 $loc_pref = "$dir_loc/";
983 if ( $byd_flag < 0 ) { # must be finddepth, report dirname now
984 unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
985 unless (chdir $updir_loc) { # $updir_loc (parent dir) is always untainted
986 warn "Can't cd to $updir_loc: $!\n";
990 $fullname = $dir_loc; # $File::Find::fullname
991 $name = $dir_name; # $File::Find::name
993 if ($dir_rel eq ':') { # must be the top dir, where we started
994 $name =~ s|:$||; # $File::Find::name
995 $p_dir = "$p_dir:" unless ($p_dir =~ /:$/);
997 $dir = $p_dir; # $File::Find::dir
998 $_ = ($no_chdir ? $name : $dir_rel); # $_
1001 if ( substr($name,-2) eq '/.' ) {
1002 $name =~ s|/\.$||; # $File::Find::name
1004 $dir = $p_dir; # $File::Find::dir
1005 $_ = ($no_chdir ? $dir_name : $dir_rel); # $_
1006 if ( substr($_,-2) eq '/.' ) {
1011 lstat($_); # make sure file tests with '_' work
1012 { &$wanted_callback }; # protect against wild "next"
1015 push @Stack,[$dir_loc, $updir_loc, $p_dir, $dir_rel,-1] if $bydepth;
1025 if ( ref($wanted) eq 'HASH' ) {
1026 if ( $wanted->{follow} || $wanted->{follow_fast}) {
1027 $wanted->{follow_skip} = 1 unless defined $wanted->{follow_skip};
1029 if ( $wanted->{untaint} ) {
1030 $wanted->{untaint_pattern} = $File::Find::untaint_pattern
1031 unless defined $wanted->{untaint_pattern};
1032 $wanted->{untaint_skip} = 0 unless defined $wanted->{untaint_skip};
1037 return { wanted => $wanted };
1043 _find_opt(wrap_wanted($wanted), @_);
1047 my $wanted = wrap_wanted(shift);
1048 $wanted->{bydepth} = 1;
1049 _find_opt($wanted, @_);
1053 $File::Find::skip_pattern = qr/^\.{1,2}\z/;
1054 $File::Find::untaint_pattern = qr|^([-+@\w./]+)$|;
1056 # These are hard-coded for now, but may move to hint files.
1059 $File::Find::dont_use_nlink = 1;
1061 elsif ($^O eq 'MacOS') {
1063 $File::Find::dont_use_nlink = 1;
1064 $File::Find::skip_pattern = qr/^Icon\015\z/;
1065 $File::Find::untaint_pattern = qr|^(.+)$|;
1068 # this _should_ work properly on all platforms
1069 # where File::Find can be expected to work
1070 $File::Find::current_dir = File::Spec->curdir || '.';
1072 $File::Find::dont_use_nlink = 1
1073 if $^O eq 'os2' || $^O eq 'dos' || $^O eq 'amigaos' || $^O eq 'MSWin32' ||
1074 $^O eq 'cygwin' || $^O eq 'epoc';
1076 # Set dont_use_nlink in your hint file if your system's stat doesn't
1077 # report the number of links in a directory as an indication
1078 # of the number of files.
1079 # See, e.g. hints/machten.sh for MachTen 2.2.
1080 unless ($File::Find::dont_use_nlink) {
1082 $File::Find::dont_use_nlink = 1 if ($Config::Config{'dont_use_nlink'});
1085 # We need a function that checks if a scalar is tainted. Either use the
1086 # Scalar::Util module's tainted() function or our (slower) pure Perl
1087 # fallback is_tainted_pp()
1090 eval { require Scalar::Util };
1091 *is_tainted = $@ ? \&is_tainted_pp : \&Scalar::Util::tainted;