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;
285 my ($wanted_callback, $avoid_nlink, $bydepth, $no_chdir, $follow,
286 $follow_skip, $full_check, $untaint, $untaint_skip, $untaint_pat,
287 $pre_process, $post_process);
292 return substr($cdir,0,rindex($cdir,'/')) if $fn eq $File::Find::current_dir;
294 $cdir = substr($cdir,0,rindex($cdir,'/')+1);
298 my $abs_name= $cdir . $fn;
300 if (substr($fn,0,3) eq '../') {
301 1 while $abs_name =~ s!/[^/]*/\.\./!/!;
307 # return the absolute name of a directory or file
308 sub contract_name_Mac {
312 if ($fn =~ /^(:+)(.*)$/) { # valid pathname starting with a ':'
314 my $colon_count = length ($1);
315 if ($colon_count == 1) {
316 $abs_name = $cdir . $2;
320 # need to move up the tree, but
321 # only if it's not a volume name
322 for (my $i=1; $i<$colon_count; $i++) {
323 unless ($cdir =~ /^[^:]+:$/) { # volume name
324 $cdir =~ s/[^:]+:$//;
330 $abs_name = $cdir . $2;
337 # $fn may be a valid path to a directory or file or (dangling)
338 # symlink, without a leading ':'
339 if ( (-e $fn) || (-l $fn) ) {
340 if ($fn =~ /^[^:]+:/) { # a volume name like DataHD:*
341 return $fn; # $fn is already an absolute path
344 $abs_name = $cdir . $fn;
348 else { # argh!, $fn is not a valid directory/file
354 sub PathCombine($$) {
355 my ($Base,$Name) = @_;
359 # $Name is the resolved symlink (always a full path on MacOS),
360 # i.e. there's no need to call contract_name_Mac()
363 # (simple) check for recursion
364 if ( ( $Base =~ /^$AbsName/) && (-d $AbsName) ) { # recursion
369 if (substr($Name,0,1) eq '/') {
373 $AbsName= contract_name($Base,$Name);
376 # (simple) check for recursion
377 my $newlen= length($AbsName);
378 if ($newlen <= length($Base)) {
379 if (($newlen == length($Base) || substr($Base,$newlen,1) eq '/')
380 && $AbsName eq substr($Base,0,$newlen))
389 sub Follow_SymLink($) {
392 my ($NewName,$DEV, $INO);
393 ($DEV, $INO)= lstat $AbsName;
396 if ($SLnkSeen{$DEV, $INO}++) {
397 if ($follow_skip < 2) {
398 die "$AbsName is encountered a second time";
404 $NewName= PathCombine($AbsName, readlink($AbsName));
405 unless(defined $NewName) {
406 if ($follow_skip < 2) {
407 die "$AbsName is a recursive symbolic link";
416 ($DEV, $INO) = lstat($AbsName);
417 return undef unless defined $DEV; # dangling symbolic link
420 if ($full_check && $SLnkSeen{$DEV, $INO}++) {
421 if ( ($follow_skip < 1) || ((-d _) && ($follow_skip < 2)) ) {
422 die "$AbsName encountered a second time";
432 our($dir, $name, $fullname, $prune);
433 sub _find_dir_symlnk($$$);
436 # check whether or not a scalar variable is tainted
437 # (code straight from the Camel, 3rd ed., page 561)
440 my $nada = substr($arg, 0, 0); # zero-length
442 eval { eval "# $nada" };
443 return length($@) != 0;
448 die "invalid top directory" unless defined $_[0];
450 my $cwd = $wanted->{bydepth} ? Cwd::fastcwd() : Cwd::cwd();
451 my $cwd_untainted = $cwd;
453 $wanted_callback = $wanted->{wanted};
454 $bydepth = $wanted->{bydepth};
455 $pre_process = $wanted->{preprocess};
456 $post_process = $wanted->{postprocess};
457 $no_chdir = $wanted->{no_chdir};
458 $full_check = $wanted->{follow};
459 $follow = $full_check || $wanted->{follow_fast};
460 $follow_skip = $wanted->{follow_skip};
461 $untaint = $wanted->{untaint};
462 $untaint_pat = $wanted->{untaint_pattern};
463 $untaint_skip = $wanted->{untaint_skip};
465 # for compatability reasons (find.pl, find2perl)
466 our ($topdir, $topdev, $topino, $topmode, $topnlink);
468 # a symbolic link to a directory doesn't increase the link count
469 $avoid_nlink = $follow || $File::Find::dont_use_nlink;
471 my ($abs_dir, $Is_Dir);
474 foreach my $TOP (@_) {
478 ($topdev,$topino,$topmode,$topnlink) = $follow ? stat $top_item : lstat $top_item;
479 $top_item = ":$top_item"
480 if ( (-d _) && ($top_item =~ /^[^:]+\z/) );
483 $top_item =~ s|/\z|| unless $top_item eq '/';
484 ($topdev,$topino,$topmode,$topnlink) = $follow ? stat $top_item : lstat $top_item;
492 $cwd = "$cwd:" unless ($cwd =~ /:$/); # for safety
494 if ($top_item eq $File::Find::current_dir) {
498 $abs_dir = contract_name_Mac($cwd, $top_item);
499 unless (defined $abs_dir) {
500 warn "Can't determine absolute path for $top_item (No such file or directory)\n";
507 if (substr($top_item,0,1) eq '/') {
508 $abs_dir = $top_item;
510 elsif ($top_item eq $File::Find::current_dir) {
513 else { # care about any ../
514 $abs_dir = contract_name("$cwd/",$top_item);
517 $abs_dir= Follow_SymLink($abs_dir);
518 unless (defined $abs_dir) {
519 warn "$top_item is a dangling symbolic link\n";
524 _find_dir_symlnk($wanted, $abs_dir, $top_item);
530 unless (defined $topnlink) {
531 warn "Can't stat $top_item: $!\n";
535 $top_item =~ s/\.dir\z// if $Is_VMS;
536 _find_dir($wanted, $top_item, $topnlink);
545 unless (($_,$dir) = File::Basename::fileparse($abs_dir)) {
547 ($dir,$_) = (':', $top_item); # $File::Find::dir, $_
550 ($dir,$_) = ('./', $top_item);
555 if (( $untaint ) && (is_tainted($dir) )) {
556 ( $abs_dir ) = $dir =~ m|$untaint_pat|;
557 unless (defined $abs_dir) {
558 if ($untaint_skip == 0) {
559 die "directory $dir is still tainted";
567 unless ($no_chdir || chdir $abs_dir) {
568 warn "Couldn't chdir $abs_dir: $!\n";
572 $name = $abs_dir . $_; # $File::Find::name
574 { &$wanted_callback }; # protect against wild "next"
578 unless ( $no_chdir ) {
579 if ( ($check_t_cwd) && (($untaint) && (is_tainted($cwd) )) ) {
580 ( $cwd_untainted ) = $cwd =~ m|$untaint_pat|;
581 unless (defined $cwd_untainted) {
582 die "insecure cwd in find(depth)";
586 unless (chdir $cwd_untainted) {
587 die "Can't cd to $cwd: $!\n";
595 # $p_dir : "parent directory"
596 # $nlink : what came back from the stat
598 # chdir (if not no_chdir) to dir
601 my ($wanted, $p_dir, $nlink) = @_;
602 my ($CdLvl,$Level) = (0,0);
605 my ($subcount,$sub_nlink);
607 my $dir_name= $p_dir;
613 $dir_pref= ($p_dir =~ /:$/) ? $p_dir : "$p_dir:"; # preface
614 $dir_rel= ':'; # directory name relative to current directory
617 $dir_pref= ( $p_dir eq '/' ? '/' : "$p_dir/" );
618 $dir_rel= '.'; # directory name relative to current directory
621 local ($dir, $name, $prune, *DIR);
623 unless ( $no_chdir || ($p_dir eq $File::Find::current_dir)) {
625 if (( $untaint ) && (is_tainted($p_dir) )) {
626 ( $udir ) = $p_dir =~ m|$untaint_pat|;
627 unless (defined $udir) {
628 if ($untaint_skip == 0) {
629 die "directory $p_dir is still tainted";
636 unless (chdir $udir) {
637 warn "Can't cd to $udir: $!\n";
642 # push the starting directory
643 push @Stack,[$CdLvl,$p_dir,$dir_rel,-1] if $bydepth;
646 $p_dir = $dir_pref; # ensure trailing ':'
649 while (defined $SE) {
651 $dir= $p_dir; # $File::Find::dir
652 $name= $dir_name; # $File::Find::name
653 $_= ($no_chdir ? $dir_name : $dir_rel ); # $_
654 # prune may happen here
656 { &$wanted_callback }; # protect against wild "next"
660 # change to that directory
661 unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
663 if ( ($untaint) && (($tainted) || ($tainted = is_tainted($dir_rel) )) ) {
664 ( $udir ) = $dir_rel =~ m|$untaint_pat|;
665 unless (defined $udir) {
666 if ($untaint_skip == 0) {
668 die "directory ($p_dir) $dir_rel is still tainted";
671 die "directory (" . ($p_dir ne '/' ? $p_dir : '') . "/) $dir_rel is still tainted";
673 } else { # $untaint_skip == 1
678 unless (chdir $udir) {
680 warn "Can't cd to ($p_dir) $udir: $!\n";
683 warn "Can't cd to (" . ($p_dir ne '/' ? $p_dir : '') . "/) $udir: $!\n";
691 $dir_name = "$dir_name:" unless ($dir_name =~ /:$/);
694 $dir= $dir_name; # $File::Find::dir
696 # Get the list of files in the current directory.
697 unless (opendir DIR, ($no_chdir ? $dir_name : $File::Find::current_dir)) {
698 warn "Can't opendir($dir_name): $!\n";
701 @filenames = readdir DIR;
703 @filenames = &$pre_process(@filenames) if $pre_process;
704 push @Stack,[$CdLvl,$dir_name,"",-2] if $post_process;
706 if ($nlink == 2 && !$avoid_nlink) {
707 # This dir has no subdirectories.
708 for my $FN (@filenames) {
709 next if $FN =~ $File::Find::skip_pattern;
711 $name = $dir_pref . $FN; # $File::Find::name
712 $_ = ($no_chdir ? $name : $FN); # $_
713 { &$wanted_callback }; # protect against wild "next"
718 # This dir has subdirectories.
719 $subcount = $nlink - 2;
721 for my $FN (@filenames) {
722 next if $FN =~ $File::Find::skip_pattern;
723 if ($subcount > 0 || $avoid_nlink) {
724 # Seen all the subdirs?
725 # check for directoriness.
726 # stat is faster for a file in the current directory
727 $sub_nlink = (lstat ($no_chdir ? $dir_pref . $FN : $FN))[3];
731 $FN =~ s/\.dir\z// if $Is_VMS;
732 push @Stack,[$CdLvl,$dir_name,$FN,$sub_nlink];
735 $name = $dir_pref . $FN; # $File::Find::name
736 $_= ($no_chdir ? $name : $FN); # $_
737 { &$wanted_callback }; # protect against wild "next"
741 $name = $dir_pref . $FN; # $File::Find::name
742 $_= ($no_chdir ? $name : $FN); # $_
743 { &$wanted_callback }; # protect against wild "next"
749 while ( defined ($SE = pop @Stack) ) {
750 ($Level, $p_dir, $dir_rel, $nlink) = @$SE;
751 if ($CdLvl > $Level && !$no_chdir) {
754 $tmp = (':' x ($CdLvl-$Level)) . ':';
757 $tmp = join('/',('..') x ($CdLvl-$Level));
759 die "Can't cd to $dir_name" . $tmp
765 # $pdir always has a trailing ':', except for the starting dir,
766 # where $dir_rel eq ':'
767 $dir_name = "$p_dir$dir_rel";
768 $dir_pref = "$dir_name:";
771 $dir_name = ($p_dir eq '/' ? "/$dir_rel" : "$p_dir/$dir_rel");
772 $dir_pref = "$dir_name/";
775 if ( $nlink == -2 ) {
776 $name = $dir = $p_dir; # $File::Find::name / dir
783 &$post_process; # End-of-directory processing
785 elsif ( $nlink < 0 ) { # must be finddepth, report dirname now
788 if ($dir_rel eq ':') { # must be the top dir, where we started
789 $name =~ s|:$||; # $File::Find::name
790 $p_dir = "$p_dir:" unless ($p_dir =~ /:$/);
792 $dir = $p_dir; # $File::Find::dir
793 $_ = ($no_chdir ? $name : $dir_rel); # $_
796 if ( substr($name,-2) eq '/.' ) {
800 $_ = ($no_chdir ? $dir_name : $dir_rel );
801 if ( substr($_,-2) eq '/.' ) {
805 { &$wanted_callback }; # protect against wild "next"
808 push @Stack,[$CdLvl,$p_dir,$dir_rel,-1] if $bydepth;
818 # $dir_loc : absolute location of a dir
819 # $p_dir : "parent directory"
821 # chdir (if not no_chdir) to dir
823 sub _find_dir_symlnk($$$) {
824 my ($wanted, $dir_loc, $p_dir) = @_; # $dir_loc is the absolute directory
828 my $updir_loc = $dir_loc; # untainted parent directory
830 my $dir_name = $p_dir;
834 my $byd_flag; # flag for pending stack entry if $bydepth
839 $dir_pref = ($p_dir =~ /:$/) ? "$p_dir" : "$p_dir:";
840 $loc_pref = ($dir_loc =~ /:$/) ? "$dir_loc" : "$dir_loc:";
841 $dir_rel = ':'; # directory name relative to current directory
843 $dir_pref = ( $p_dir eq '/' ? '/' : "$p_dir/" );
844 $loc_pref = ( $dir_loc eq '/' ? '/' : "$dir_loc/" );
845 $dir_rel = '.'; # directory name relative to current directory
848 local ($dir, $name, $fullname, $prune, *DIR);
852 if (( $untaint ) && (is_tainted($dir_loc) )) {
853 ( $updir_loc ) = $dir_loc =~ m|$untaint_pat|; # parent dir, now untainted
854 # once untainted, $updir_loc is pushed on the stack (as parent directory);
855 # hence, we don't need to untaint the parent directory every time we chdir
857 unless (defined $updir_loc) {
858 if ($untaint_skip == 0) {
859 die "directory $dir_loc is still tainted";
866 $ok = chdir($updir_loc) unless ($p_dir eq $File::Find::current_dir);
868 warn "Can't cd to $updir_loc: $!\n";
873 push @Stack,[$dir_loc,$updir_loc,$p_dir,$dir_rel,-1] if $bydepth;
876 $p_dir = $dir_pref; # ensure trailing ':'
879 while (defined $SE) {
882 # change (back) to parent directory (always untainted)
884 unless (chdir $updir_loc) {
885 warn "Can't cd to $updir_loc: $!\n";
889 $dir= $p_dir; # $File::Find::dir
890 $name= $dir_name; # $File::Find::name
891 $_= ($no_chdir ? $dir_name : $dir_rel ); # $_
892 $fullname= $dir_loc; # $File::Find::fullname
893 # prune may happen here
895 lstat($_); # make sure file tests with '_' work
896 { &$wanted_callback }; # protect against wild "next"
900 # change to that directory
901 unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
902 $updir_loc = $dir_loc;
903 if ( ($untaint) && (($tainted) || ($tainted = is_tainted($dir_loc) )) ) {
904 # untaint $dir_loc, what will be pushed on the stack as (untainted) parent dir
905 ( $updir_loc ) = $dir_loc =~ m|$untaint_pat|;
906 unless (defined $updir_loc) {
907 if ($untaint_skip == 0) {
908 die "directory $dir_loc is still tainted";
915 unless (chdir $updir_loc) {
916 warn "Can't cd to $updir_loc: $!\n";
922 $dir_name = "$dir_name:" unless ($dir_name =~ /:$/);
925 $dir = $dir_name; # $File::Find::dir
927 # Get the list of files in the current directory.
928 unless (opendir DIR, ($no_chdir ? $dir_loc : $File::Find::current_dir)) {
929 warn "Can't opendir($dir_loc): $!\n";
932 @filenames = readdir DIR;
935 for my $FN (@filenames) {
936 next if $FN =~ $File::Find::skip_pattern;
938 # follow symbolic links / do an lstat
939 $new_loc = Follow_SymLink($loc_pref.$FN);
941 # ignore if invalid symlink
942 next unless defined $new_loc;
945 push @Stack,[$new_loc,$updir_loc,$dir_name,$FN,1];
948 $fullname = $new_loc; # $File::Find::fullname
949 $name = $dir_pref . $FN; # $File::Find::name
950 $_ = ($no_chdir ? $name : $FN); # $_
951 { &$wanted_callback }; # protect against wild "next"
957 while (defined($SE = pop @Stack)) {
958 ($dir_loc, $updir_loc, $p_dir, $dir_rel, $byd_flag) = @$SE;
960 # $p_dir always has a trailing ':', except for the starting dir,
961 # where $dir_rel eq ':'
962 $dir_name = "$p_dir$dir_rel";
963 $dir_pref = "$dir_name:";
964 $loc_pref = ($dir_loc =~ /:$/) ? $dir_loc : "$dir_loc:";
967 $dir_name = ($p_dir eq '/' ? "/$dir_rel" : "$p_dir/$dir_rel");
968 $dir_pref = "$dir_name/";
969 $loc_pref = "$dir_loc/";
971 if ( $byd_flag < 0 ) { # must be finddepth, report dirname now
972 unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
973 unless (chdir $updir_loc) { # $updir_loc (parent dir) is always untainted
974 warn "Can't cd to $updir_loc: $!\n";
978 $fullname = $dir_loc; # $File::Find::fullname
979 $name = $dir_name; # $File::Find::name
981 if ($dir_rel eq ':') { # must be the top dir, where we started
982 $name =~ s|:$||; # $File::Find::name
983 $p_dir = "$p_dir:" unless ($p_dir =~ /:$/);
985 $dir = $p_dir; # $File::Find::dir
986 $_ = ($no_chdir ? $name : $dir_rel); # $_
989 if ( substr($name,-2) eq '/.' ) {
990 $name =~ s|/\.$||; # $File::Find::name
992 $dir = $p_dir; # $File::Find::dir
993 $_ = ($no_chdir ? $dir_name : $dir_rel); # $_
994 if ( substr($_,-2) eq '/.' ) {
999 lstat($_); # make sure file tests with '_' work
1000 { &$wanted_callback }; # protect against wild "next"
1003 push @Stack,[$dir_loc, $updir_loc, $p_dir, $dir_rel,-1] if $bydepth;
1013 if ( ref($wanted) eq 'HASH' ) {
1014 if ( $wanted->{follow} || $wanted->{follow_fast}) {
1015 $wanted->{follow_skip} = 1 unless defined $wanted->{follow_skip};
1017 if ( $wanted->{untaint} ) {
1018 $wanted->{untaint_pattern} = $File::Find::untaint_pattern
1019 unless defined $wanted->{untaint_pattern};
1020 $wanted->{untaint_skip} = 0 unless defined $wanted->{untaint_skip};
1025 return { wanted => $wanted };
1031 %SLnkSeen= (); # clear hash first
1032 _find_opt(wrap_wanted($wanted), @_);
1033 %SLnkSeen= (); # free memory
1037 my $wanted = wrap_wanted(shift);
1038 %SLnkSeen= (); # clear hash first
1039 $wanted->{bydepth} = 1;
1040 _find_opt($wanted, @_);
1041 %SLnkSeen= (); # free memory
1045 $File::Find::skip_pattern = qr/^\.{1,2}\z/;
1046 $File::Find::untaint_pattern = qr|^([-+@\w./]+)$|;
1048 # These are hard-coded for now, but may move to hint files.
1051 $File::Find::dont_use_nlink = 1;
1053 elsif ($^O eq 'MacOS') {
1055 $File::Find::dont_use_nlink = 1;
1056 $File::Find::skip_pattern = qr/^Icon\015\z/;
1057 $File::Find::untaint_pattern = qr|^(.+)$|;
1060 # this _should_ work properly on all platforms
1061 # where File::Find can be expected to work
1062 $File::Find::current_dir = File::Spec->curdir || '.';
1064 $File::Find::dont_use_nlink = 1
1065 if $^O eq 'os2' || $^O eq 'dos' || $^O eq 'amigaos' || $^O eq 'MSWin32' ||
1066 $^O eq 'cygwin' || $^O eq 'epoc';
1068 # Set dont_use_nlink in your hint file if your system's stat doesn't
1069 # report the number of links in a directory as an indication
1070 # of the number of files.
1071 # See, e.g. hints/machten.sh for MachTen 2.2.
1072 unless ($File::Find::dont_use_nlink) {
1074 $File::Find::dont_use_nlink = 1 if ($Config::Config{'dont_use_nlink'});
1077 # We need a function that checks if a scalar is tainted. Either use the
1078 # Scalar::Util module's tainted() function or our (slower) pure Perl
1079 # fallback is_tainted_pp()
1082 eval { require Scalar::Util };
1083 *is_tainted = $@ ? \&is_tainted_pp : \&Scalar::Util::tainted;