5 use warnings::register;
11 # Modified to ensure sub-directory traversal order is not inverded by stack
12 # push and pops. That is remains in the same order as in the directory file,
13 # or user pre-processing (EG:sorted).
18 File::Find - Traverse a directory tree.
23 find(\&wanted, @directories_to_search);
27 finddepth(\&wanted, @directories_to_search);
31 find({ wanted => \&process, follow => 1 }, '.');
35 These are functions for searching through directory trees doing work
36 on each file found similar to the Unix I<find> command. File::Find
37 exports two functions, C<find> and C<finddepth>. They work similarly
38 but have subtle differences.
44 find(\&wanted, @directories);
45 find(\%options, @directories);
47 C<find()> does a breadth-first search over the given C<@directories> in the
48 order they are given. In essence, it works from the top down.
50 For each file or directory found, the C<&wanted> subroutine is called,
51 with the return code ignored. (See below for details on how to use
52 the C<&wanted> function). Additionally, for each directory found,
53 it will go into that directory and continue the search.
57 finddepth(\&wanted, @directories);
58 finddepth(\%options, @directories);
60 C<finddepth()> works just like C<find()> except it does a depth-first search.
61 It works from the bottom of the directory tree up.
67 The first argument to C<find()> is either a code reference to your
68 C<&wanted> function, or a hash reference describing the operations
69 to be performed for each file. The
70 code reference is described in L<The wanted function> below.
72 Here are the possible keys for the hash:
78 The value should be a code reference. This code reference is
79 described in L<The wanted function> below.
83 Reports the name of a directory only AFTER all its entries
84 have been reported. Entry point C<finddepth()> is a shortcut for
85 specifying C<<{ bydepth => 1 }>> in the first argument of C<find()>.
89 The value should be a code reference. This code reference is used to
90 preprocess the current directory. The name of the currently processed
91 directory is in C<$File::Find::dir>. Your preprocessing function is
92 called after C<readdir()>, but before the loop that calls the C<wanted()>
93 function. It is called with a list of strings (actually file/directory
94 names) and is expected to return a list of strings. The code can be
95 used to sort the file/directory names alphabetically, numerically,
96 or to filter out directory entries based on their name alone. When
97 I<follow> or I<follow_fast> are in effect, C<preprocess> is a no-op.
101 The value should be a code reference. It is invoked just before leaving
102 the currently processed directory. It is called in void context with no
103 arguments. The name of the current directory is in C<$File::Find::dir>. This
104 hook is handy for summarizing a directory, such as calculating its disk
105 usage. When I<follow> or I<follow_fast> are in effect, C<postprocess> is a
110 Causes symbolic links to be followed. Since directory trees with symbolic
111 links (followed) may contain files more than once and may even have
112 cycles, a hash has to be built up with an entry for each file.
113 This might be expensive both in space and time for a large
114 directory tree. See I<follow_fast> and I<follow_skip> below.
115 If either I<follow> or I<follow_fast> is in effect:
121 It is guaranteed that an I<lstat> has been called before the user's
122 C<wanted()> function is called. This enables fast file checks involving S< _>.
126 There is a variable C<$File::Find::fullname> which holds the absolute
127 pathname of the file with all symbolic links resolved
133 This is similar to I<follow> except that it may report some files more
134 than once. It does detect cycles, however. Since only symbolic links
135 have to be hashed, this is much cheaper both in space and time. If
136 processing a file more than once (by the user's C<wanted()> function)
137 is worse than just taking time, the option I<follow> should be used.
141 C<follow_skip==1>, which is the default, causes all files which are
142 neither directories nor symbolic links to be ignored if they are about
143 to be processed a second time. If a directory or a symbolic link
144 are about to be processed a second time, File::Find dies.
146 C<follow_skip==0> causes File::Find to die if any file is about to be
147 processed a second time.
149 C<follow_skip==2> causes File::Find to ignore any duplicate files and
150 directories but to proceed normally otherwise.
152 =item C<dangling_symlinks>
154 If true and a code reference, will be called with the symbolic link
155 name and the directory it lives in as arguments. Otherwise, if true
156 and warnings are on, warning "symbolic_link_name is a dangling
157 symbolic link\n" will be issued. If false, the dangling symbolic link
158 will be silently ignored.
162 Does not C<chdir()> to each directory as it recurses. The C<wanted()>
163 function will need to be aware of this, of course. In this case,
164 C<$_> will be the same as C<$File::Find::name>.
168 If find is used in taint-mode (-T command line switch or if EUID != UID
169 or if EGID != GID) then internally directory names have to be untainted
170 before they can be chdir'ed to. Therefore they are checked against a regular
171 expression I<untaint_pattern>. Note that all names passed to the user's
172 I<wanted()> function are still tainted. If this option is used while
173 not in taint-mode, C<untaint> is a no-op.
175 =item C<untaint_pattern>
177 See above. This should be set using the C<qr> quoting operator.
178 The default is set to C<qr|^([-+@\w./]+)$|>.
179 Note that the parentheses are vital.
181 =item C<untaint_skip>
183 If set, a directory which fails the I<untaint_pattern> is skipped,
184 including all its sub-directories. The default is to 'die' in such a case.
188 =head2 The wanted function
190 The C<wanted()> function does whatever verifications you want on
191 each file and directory. Note that despite its name, the C<wanted()>
192 function is a generic callback function, and does B<not> tell
193 File::Find if a file is "wanted" or not. In fact, its return value
196 The wanted function takes no arguments but rather does its work
197 through a collection of variables.
201 =item C<$File::Find::dir> is the current directory name,
203 =item C<$_> is the current filename within that directory
205 =item C<$File::Find::name> is the complete pathname to the file.
209 Don't modify these variables.
211 For example, when examining the file F</some/path/foo.ext> you will have:
213 $File::Find::dir = /some/path/
215 $File::Find::name = /some/path/foo.ext
217 You are chdir()'d toC<$File::Find::dir> when the function is called,
218 unless C<no_chdir> was specified. Note that when changing to
219 directories is in effect the root directory (F</>) is a somewhat
220 special case inasmuch as the concatenation of C<$File::Find::dir>,
221 C<'/'> and C<$_> is not literally equal to C<$File::Find::name>. The
222 table below summarizes all variants:
224 $File::Find::name $File::Find::dir $_
226 no_chdir=>0 /etc / etc
234 When <follow> or <follow_fast> are in effect, there is
235 also a C<$File::Find::fullname>. The function may set
236 C<$File::Find::prune> to prune the tree unless C<bydepth> was
237 specified. Unless C<follow> or C<follow_fast> is specified, for
238 compatibility reasons (find.pl, find2perl) there are in addition the
239 following globals available: C<$File::Find::topdir>,
240 C<$File::Find::topdev>, C<$File::Find::topino>,
241 C<$File::Find::topmode> and C<$File::Find::topnlink>.
243 This library is useful for the C<find2perl> tool, which when fed,
245 find2perl / -name .nfs\* -mtime +7 \
246 -exec rm -f {} \; -o -fstype nfs -prune
248 produces something like:
252 (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_)) &&
256 ($nlink || (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_))) &&
258 ($File::Find::prune = 1);
261 Notice the C<_> in the above C<int(-M _)>: the C<_> is a magical
262 filehandle that caches the information from the preceding
263 C<stat()>, C<lstat()>, or filetest.
265 Here's another interesting wanted function. It will find all symbolic
266 links that don't resolve:
269 -l && !-e && print "bogus link: $File::Find::name\n";
272 See also the script C<pfind> on CPAN for a nice application of this
277 If you run your program with the C<-w> switch, or if you use the
278 C<warnings> pragma, File::Find will report warnings for several weird
279 situations. You can disable these warnings by putting the statement
281 no warnings 'File::Find';
283 in the appropriate scope. See L<perllexwarn> for more info about lexical
290 =item $dont_use_nlink
292 You can set the variable C<$File::Find::dont_use_nlink> to 1, if you want to
293 force File::Find to always stat directories. This was used for file systems
294 that do not have an C<nlink> count matching the number of sub-directories.
295 Examples are ISO-9660 (CD-ROM), AFS, HPFS (OS/2 file system), FAT (DOS file
296 system) and a couple of others.
298 You shouldn't need to set this variable, since File::Find should now detect
299 such file systems on-the-fly and switch itself to using stat. This works even
300 for parts of your file system, like a mounted CD-ROM.
302 If you do set C<$File::Find::dont_use_nlink> to 1, you will notice slow-downs.
306 Be aware that the option to follow symbolic links can be dangerous.
307 Depending on the structure of the directory tree (including symbolic
308 links to directories) you might traverse a given (physical) directory
309 more than once (only if C<follow_fast> is in effect).
310 Furthermore, deleting or changing files in a symbolically linked directory
311 might cause very unpleasant surprises, since you delete or change files
312 in an unknown directory.
322 Mac OS (Classic) users should note a few differences:
328 The path separator is ':', not '/', and the current directory is denoted
329 as ':', not '.'. You should be careful about specifying relative pathnames.
330 While a full path always begins with a volume name, a relative pathname
331 should always begin with a ':'. If specifying a volume name only, a
332 trailing ':' is required.
336 C<$File::Find::dir> is guaranteed to end with a ':'. If C<$_>
337 contains the name of a directory, that name may or may not end with a
338 ':'. Likewise, C<$File::Find::name>, which contains the complete
339 pathname to that directory, and C<$File::Find::fullname>, which holds
340 the absolute pathname of that directory with all symbolic links resolved,
341 may or may not end with a ':'.
345 The default C<untaint_pattern> (see above) on Mac OS is set to
346 C<qr|^(.+)$|>. Note that the parentheses are vital.
350 The invisible system file "Icon\015" is ignored. While this file may
351 appear in every directory, there are some more invisible system files
352 on every volume, which are all located at the volume root level (i.e.
353 "MacintoshHD:"). These system files are B<not> excluded automatically.
354 Your filter may use the following code to recognize invisible files or
355 directories (requires Mac::Files):
359 # invisible() -- returns 1 if file/directory is invisible,
360 # 0 if it's visible or undef if an error occurred
364 my ($fileCat, $fileInfo);
365 my $invisible_flag = 1 << 14;
367 if ( $fileCat = FSpGetCatInfo($file) ) {
368 if ($fileInfo = $fileCat->ioFlFndrInfo() ) {
369 return (($fileInfo->fdFlags & $invisible_flag) && 1);
375 Generally, invisible files are system files, unless an odd application
376 decides to use invisible files for its own purposes. To distinguish
377 such files from system files, you have to look at the B<type> and B<creator>
378 file attributes. The MacPerl built-in functions C<GetFileInfo(FILE)> and
379 C<SetFileInfo(CREATOR, TYPE, FILES)> offer access to these attributes
380 (see MacPerl.pm for details).
382 Files that appear on the desktop actually reside in an (hidden) directory
383 named "Desktop Folder" on the particular disk volume. Note that, although
384 all desktop files appear to be on the same "virtual" desktop, each disk
385 volume actually maintains its own "Desktop Folder" directory.
393 File::Find used to produce incorrect results if called recursively.
394 During the development of perl 5.8 this bug was fixed.
395 The first fixed version of File::Find was 1.01.
399 our @ISA = qw(Exporter);
400 our @EXPORT = qw(find finddepth);
407 require File::Basename;
410 # Should ideally be my() not our() but local() currently
411 # refuses to operate on lexicals
414 our ($wanted_callback, $avoid_nlink, $bydepth, $no_chdir, $follow,
415 $follow_skip, $full_check, $untaint, $untaint_skip, $untaint_pat,
416 $pre_process, $post_process, $dangling_symlinks);
421 return substr($cdir,0,rindex($cdir,'/')) if $fn eq $File::Find::current_dir;
423 $cdir = substr($cdir,0,rindex($cdir,'/')+1);
427 my $abs_name= $cdir . $fn;
429 if (substr($fn,0,3) eq '../') {
430 1 while $abs_name =~ s!/[^/]*/\.\./!/!;
436 # return the absolute name of a directory or file
437 sub contract_name_Mac {
441 if ($fn =~ /^(:+)(.*)$/) { # valid pathname starting with a ':'
443 my $colon_count = length ($1);
444 if ($colon_count == 1) {
445 $abs_name = $cdir . $2;
449 # need to move up the tree, but
450 # only if it's not a volume name
451 for (my $i=1; $i<$colon_count; $i++) {
452 unless ($cdir =~ /^[^:]+:$/) { # volume name
453 $cdir =~ s/[^:]+:$//;
459 $abs_name = $cdir . $2;
466 # $fn may be a valid path to a directory or file or (dangling)
467 # symlink, without a leading ':'
468 if ( (-e $fn) || (-l $fn) ) {
469 if ($fn =~ /^[^:]+:/) { # a volume name like DataHD:*
470 return $fn; # $fn is already an absolute path
473 $abs_name = $cdir . $fn;
477 else { # argh!, $fn is not a valid directory/file
483 sub PathCombine($$) {
484 my ($Base,$Name) = @_;
488 # $Name is the resolved symlink (always a full path on MacOS),
489 # i.e. there's no need to call contract_name_Mac()
492 # (simple) check for recursion
493 if ( ( $Base =~ /^$AbsName/) && (-d $AbsName) ) { # recursion
498 if (substr($Name,0,1) eq '/') {
502 $AbsName= contract_name($Base,$Name);
505 # (simple) check for recursion
506 my $newlen= length($AbsName);
507 if ($newlen <= length($Base)) {
508 if (($newlen == length($Base) || substr($Base,$newlen,1) eq '/')
509 && $AbsName eq substr($Base,0,$newlen))
518 sub Follow_SymLink($) {
521 my ($NewName,$DEV, $INO);
522 ($DEV, $INO)= lstat $AbsName;
525 if ($SLnkSeen{$DEV, $INO}++) {
526 if ($follow_skip < 2) {
527 die "$AbsName is encountered a second time";
533 $NewName= PathCombine($AbsName, readlink($AbsName));
534 unless(defined $NewName) {
535 if ($follow_skip < 2) {
536 die "$AbsName is a recursive symbolic link";
545 ($DEV, $INO) = lstat($AbsName);
546 return undef unless defined $DEV; # dangling symbolic link
549 if ($full_check && defined $DEV && $SLnkSeen{$DEV, $INO}++) {
550 if ( ($follow_skip < 1) || ((-d _) && ($follow_skip < 2)) ) {
551 die "$AbsName encountered a second time";
561 our($dir, $name, $fullname, $prune);
562 sub _find_dir_symlnk($$$);
565 # check whether or not a scalar variable is tainted
566 # (code straight from the Camel, 3rd ed., page 561)
569 my $nada = substr($arg, 0, 0); # zero-length
571 eval { eval "# $nada" };
572 return length($@) != 0;
577 die "invalid top directory" unless defined $_[0];
579 # This function must local()ize everything because callbacks may
580 # call find() or finddepth()
583 local ($wanted_callback, $avoid_nlink, $bydepth, $no_chdir, $follow,
584 $follow_skip, $full_check, $untaint, $untaint_skip, $untaint_pat,
585 $pre_process, $post_process, $dangling_symlinks);
586 local($dir, $name, $fullname, $prune, $_);
588 my $cwd = $wanted->{bydepth} ? Cwd::fastcwd() : Cwd::getcwd();
589 my $cwd_untainted = $cwd;
591 $wanted_callback = $wanted->{wanted};
592 $bydepth = $wanted->{bydepth};
593 $pre_process = $wanted->{preprocess};
594 $post_process = $wanted->{postprocess};
595 $no_chdir = $wanted->{no_chdir};
596 $full_check = $wanted->{follow};
597 $follow = $full_check || $wanted->{follow_fast};
598 $follow_skip = $wanted->{follow_skip};
599 $untaint = $wanted->{untaint};
600 $untaint_pat = $wanted->{untaint_pattern};
601 $untaint_skip = $wanted->{untaint_skip};
602 $dangling_symlinks = $wanted->{dangling_symlinks};
604 # for compatibility reasons (find.pl, find2perl)
605 local our ($topdir, $topdev, $topino, $topmode, $topnlink);
607 # a symbolic link to a directory doesn't increase the link count
608 $avoid_nlink = $follow || $File::Find::dont_use_nlink;
610 my ($abs_dir, $Is_Dir);
613 foreach my $TOP (@_) {
617 ($topdev,$topino,$topmode,$topnlink) = $follow ? stat $top_item : lstat $top_item;
618 $top_item = ":$top_item"
619 if ( (-d _) && ( $top_item !~ /:/ ) );
622 $top_item =~ s|/\z|| unless $top_item eq '/';
623 ($topdev,$topino,$topmode,$topnlink) = $follow ? stat $top_item : lstat $top_item;
631 $cwd = "$cwd:" unless ($cwd =~ /:$/); # for safety
633 if ($top_item eq $File::Find::current_dir) {
637 $abs_dir = contract_name_Mac($cwd, $top_item);
638 unless (defined $abs_dir) {
639 warnings::warnif "Can't determine absolute path for $top_item (No such file or directory)\n";
646 if (substr($top_item,0,1) eq '/') {
647 $abs_dir = $top_item;
649 elsif ($top_item eq $File::Find::current_dir) {
652 else { # care about any ../
653 $abs_dir = contract_name("$cwd/",$top_item);
656 $abs_dir= Follow_SymLink($abs_dir);
657 unless (defined $abs_dir) {
658 if ($dangling_symlinks) {
659 if (ref $dangling_symlinks eq 'CODE') {
660 $dangling_symlinks->($top_item, $cwd);
662 warnings::warnif "$top_item is a dangling symbolic link\n";
669 _find_dir_symlnk($wanted, $abs_dir, $top_item);
675 unless (defined $topnlink) {
676 warnings::warnif "Can't stat $top_item: $!\n";
680 $top_item =~ s/\.dir\z//i if $Is_VMS;
681 _find_dir($wanted, $top_item, $topnlink);
690 unless (($_,$dir) = File::Basename::fileparse($abs_dir)) {
692 ($dir,$_) = (':', $top_item); # $File::Find::dir, $_
695 ($dir,$_) = ('./', $top_item);
700 if (( $untaint ) && (is_tainted($dir) )) {
701 ( $abs_dir ) = $dir =~ m|$untaint_pat|;
702 unless (defined $abs_dir) {
703 if ($untaint_skip == 0) {
704 die "directory $dir is still tainted";
712 unless ($no_chdir || chdir $abs_dir) {
713 warnings::warnif "Couldn't chdir $abs_dir: $!\n";
717 $name = $abs_dir . $_; # $File::Find::name
718 $_ = $name if $no_chdir;
720 { $wanted_callback->() }; # protect against wild "next"
724 unless ( $no_chdir ) {
725 if ( ($check_t_cwd) && (($untaint) && (is_tainted($cwd) )) ) {
726 ( $cwd_untainted ) = $cwd =~ m|$untaint_pat|;
727 unless (defined $cwd_untainted) {
728 die "insecure cwd in find(depth)";
732 unless (chdir $cwd_untainted) {
733 die "Can't cd to $cwd: $!\n";
741 # $p_dir : "parent directory"
742 # $nlink : what came back from the stat
744 # chdir (if not no_chdir) to dir
747 my ($wanted, $p_dir, $nlink) = @_;
748 my ($CdLvl,$Level) = (0,0);
751 my ($subcount,$sub_nlink);
753 my $dir_name= $p_dir;
755 my $dir_rel = $File::Find::current_dir;
760 $dir_pref= ($p_dir =~ /:$/) ? $p_dir : "$p_dir:"; # preface
763 $dir_pref= ( $p_dir eq '/' ? '/' : "$p_dir/" );
766 local ($dir, $name, $prune, *DIR);
768 unless ( $no_chdir || ($p_dir eq $File::Find::current_dir)) {
770 if (( $untaint ) && (is_tainted($p_dir) )) {
771 ( $udir ) = $p_dir =~ m|$untaint_pat|;
772 unless (defined $udir) {
773 if ($untaint_skip == 0) {
774 die "directory $p_dir is still tainted";
781 unless (chdir ($Is_VMS && $udir !~ /[\/\[<]+/ ? "./$udir" : $udir)) {
782 warnings::warnif "Can't cd to $udir: $!\n";
787 # push the starting directory
788 push @Stack,[$CdLvl,$p_dir,$dir_rel,-1] if $bydepth;
791 $p_dir = $dir_pref; # ensure trailing ':'
794 while (defined $SE) {
796 $dir= $p_dir; # $File::Find::dir
797 $name= $dir_name; # $File::Find::name
798 $_= ($no_chdir ? $dir_name : $dir_rel ); # $_
799 # prune may happen here
801 { $wanted_callback->() }; # protect against wild "next"
805 # change to that directory
806 unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
808 if ( ($untaint) && (($tainted) || ($tainted = is_tainted($dir_rel) )) ) {
809 ( $udir ) = $dir_rel =~ m|$untaint_pat|;
810 unless (defined $udir) {
811 if ($untaint_skip == 0) {
813 die "directory ($p_dir) $dir_rel is still tainted";
816 die "directory (" . ($p_dir ne '/' ? $p_dir : '') . "/) $dir_rel is still tainted";
818 } else { # $untaint_skip == 1
823 unless (chdir ($Is_VMS && $udir !~ /[\/\[<]+/ ? "./$udir" : $udir)) {
825 warnings::warnif "Can't cd to ($p_dir) $udir: $!\n";
828 warnings::warnif "Can't cd to (" .
829 ($p_dir ne '/' ? $p_dir : '') . "/) $udir: $!\n";
837 $dir_name = "$dir_name:" unless ($dir_name =~ /:$/);
840 $dir= $dir_name; # $File::Find::dir
842 # Get the list of files in the current directory.
843 unless (opendir DIR, ($no_chdir ? $dir_name : $File::Find::current_dir)) {
844 warnings::warnif "Can't opendir($dir_name): $!\n";
847 @filenames = readdir DIR;
849 @filenames = $pre_process->(@filenames) if $pre_process;
850 push @Stack,[$CdLvl,$dir_name,"",-2] if $post_process;
852 # default: use whatever was specifid
853 # (if $nlink >= 2, and $avoid_nlink == 0, this will switch back)
854 $no_nlink = $avoid_nlink;
855 # if dir has wrong nlink count, force switch to slower stat method
856 $no_nlink = 1 if ($nlink < 2);
858 if ($nlink == 2 && !$no_nlink) {
859 # This dir has no subdirectories.
860 for my $FN (@filenames) {
861 next if $FN =~ $File::Find::skip_pattern;
863 $name = $dir_pref . $FN; # $File::Find::name
864 $_ = ($no_chdir ? $name : $FN); # $_
865 { $wanted_callback->() }; # protect against wild "next"
870 # This dir has subdirectories.
871 $subcount = $nlink - 2;
873 # HACK: insert directories at this position. so as to preserve
874 # the user pre-processed ordering of files.
875 # EG: directory traversal is in user sorted order, not at random.
876 my $stack_top = @Stack;
878 for my $FN (@filenames) {
879 next if $FN =~ $File::Find::skip_pattern;
880 if ($subcount > 0 || $no_nlink) {
881 # Seen all the subdirs?
882 # check for directoriness.
883 # stat is faster for a file in the current directory
884 $sub_nlink = (lstat ($no_chdir ? $dir_pref . $FN : $FN))[3];
888 $FN =~ s/\.dir\z//i if $Is_VMS;
889 # HACK: replace push to preserve dir traversal order
890 #push @Stack,[$CdLvl,$dir_name,$FN,$sub_nlink];
891 splice @Stack, $stack_top, 0,
892 [$CdLvl,$dir_name,$FN,$sub_nlink];
895 $name = $dir_pref . $FN; # $File::Find::name
896 $_= ($no_chdir ? $name : $FN); # $_
897 { $wanted_callback->() }; # protect against wild "next"
901 $name = $dir_pref . $FN; # $File::Find::name
902 $_= ($no_chdir ? $name : $FN); # $_
903 { $wanted_callback->() }; # protect against wild "next"
909 while ( defined ($SE = pop @Stack) ) {
910 ($Level, $p_dir, $dir_rel, $nlink) = @$SE;
911 if ($CdLvl > $Level && !$no_chdir) {
914 $tmp = (':' x ($CdLvl-$Level)) . ':';
917 $tmp = join('/',('..') x ($CdLvl-$Level));
919 die "Can't cd to $dir_name" . $tmp
925 # $pdir always has a trailing ':', except for the starting dir,
926 # where $dir_rel eq ':'
927 $dir_name = "$p_dir$dir_rel";
928 $dir_pref = "$dir_name:";
931 $dir_name = ($p_dir eq '/' ? "/$dir_rel" : "$p_dir/$dir_rel");
932 $dir_pref = "$dir_name/";
935 if ( $nlink == -2 ) {
936 $name = $dir = $p_dir; # $File::Find::name / dir
937 $_ = $File::Find::current_dir;
938 $post_process->(); # End-of-directory processing
940 elsif ( $nlink < 0 ) { # must be finddepth, report dirname now
943 if ($dir_rel eq ':') { # must be the top dir, where we started
944 $name =~ s|:$||; # $File::Find::name
945 $p_dir = "$p_dir:" unless ($p_dir =~ /:$/);
947 $dir = $p_dir; # $File::Find::dir
948 $_ = ($no_chdir ? $name : $dir_rel); # $_
951 if ( substr($name,-2) eq '/.' ) {
952 substr($name, length($name) == 2 ? -1 : -2) = '';
955 $_ = ($no_chdir ? $dir_name : $dir_rel );
956 if ( substr($_,-2) eq '/.' ) {
957 substr($_, length($_) == 2 ? -1 : -2) = '';
960 { $wanted_callback->() }; # protect against wild "next"
963 push @Stack,[$CdLvl,$p_dir,$dir_rel,-1] if $bydepth;
973 # $dir_loc : absolute location of a dir
974 # $p_dir : "parent directory"
976 # chdir (if not no_chdir) to dir
978 sub _find_dir_symlnk($$$) {
979 my ($wanted, $dir_loc, $p_dir) = @_; # $dir_loc is the absolute directory
983 my $updir_loc = $dir_loc; # untainted parent directory
985 my $dir_name = $p_dir;
988 my $dir_rel = $File::Find::current_dir;
989 my $byd_flag; # flag for pending stack entry if $bydepth
994 $dir_pref = ($p_dir =~ /:$/) ? "$p_dir" : "$p_dir:";
995 $loc_pref = ($dir_loc =~ /:$/) ? "$dir_loc" : "$dir_loc:";
997 $dir_pref = ( $p_dir eq '/' ? '/' : "$p_dir/" );
998 $loc_pref = ( $dir_loc eq '/' ? '/' : "$dir_loc/" );
1001 local ($dir, $name, $fullname, $prune, *DIR);
1003 unless ($no_chdir) {
1004 # untaint the topdir
1005 if (( $untaint ) && (is_tainted($dir_loc) )) {
1006 ( $updir_loc ) = $dir_loc =~ m|$untaint_pat|; # parent dir, now untainted
1007 # once untainted, $updir_loc is pushed on the stack (as parent directory);
1008 # hence, we don't need to untaint the parent directory every time we chdir
1010 unless (defined $updir_loc) {
1011 if ($untaint_skip == 0) {
1012 die "directory $dir_loc is still tainted";
1019 $ok = chdir($updir_loc) unless ($p_dir eq $File::Find::current_dir);
1021 warnings::warnif "Can't cd to $updir_loc: $!\n";
1026 push @Stack,[$dir_loc,$updir_loc,$p_dir,$dir_rel,-1] if $bydepth;
1029 $p_dir = $dir_pref; # ensure trailing ':'
1032 while (defined $SE) {
1035 # change (back) to parent directory (always untainted)
1036 unless ($no_chdir) {
1037 unless (chdir $updir_loc) {
1038 warnings::warnif "Can't cd to $updir_loc: $!\n";
1042 $dir= $p_dir; # $File::Find::dir
1043 $name= $dir_name; # $File::Find::name
1044 $_= ($no_chdir ? $dir_name : $dir_rel ); # $_
1045 $fullname= $dir_loc; # $File::Find::fullname
1046 # prune may happen here
1048 lstat($_); # make sure file tests with '_' work
1049 { $wanted_callback->() }; # protect against wild "next"
1053 # change to that directory
1054 unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
1055 $updir_loc = $dir_loc;
1056 if ( ($untaint) && (($tainted) || ($tainted = is_tainted($dir_loc) )) ) {
1057 # untaint $dir_loc, what will be pushed on the stack as (untainted) parent dir
1058 ( $updir_loc ) = $dir_loc =~ m|$untaint_pat|;
1059 unless (defined $updir_loc) {
1060 if ($untaint_skip == 0) {
1061 die "directory $dir_loc is still tainted";
1068 unless (chdir $updir_loc) {
1069 warnings::warnif "Can't cd to $updir_loc: $!\n";
1075 $dir_name = "$dir_name:" unless ($dir_name =~ /:$/);
1078 $dir = $dir_name; # $File::Find::dir
1080 # Get the list of files in the current directory.
1081 unless (opendir DIR, ($no_chdir ? $dir_loc : $File::Find::current_dir)) {
1082 warnings::warnif "Can't opendir($dir_loc): $!\n";
1085 @filenames = readdir DIR;
1088 for my $FN (@filenames) {
1089 next if $FN =~ $File::Find::skip_pattern;
1091 # follow symbolic links / do an lstat
1092 $new_loc = Follow_SymLink($loc_pref.$FN);
1094 # ignore if invalid symlink
1095 next unless defined $new_loc;
1098 push @Stack,[$new_loc,$updir_loc,$dir_name,$FN,1];
1101 $fullname = $new_loc; # $File::Find::fullname
1102 $name = $dir_pref . $FN; # $File::Find::name
1103 $_ = ($no_chdir ? $name : $FN); # $_
1104 { $wanted_callback->() }; # protect against wild "next"
1110 while (defined($SE = pop @Stack)) {
1111 ($dir_loc, $updir_loc, $p_dir, $dir_rel, $byd_flag) = @$SE;
1113 # $p_dir always has a trailing ':', except for the starting dir,
1114 # where $dir_rel eq ':'
1115 $dir_name = "$p_dir$dir_rel";
1116 $dir_pref = "$dir_name:";
1117 $loc_pref = ($dir_loc =~ /:$/) ? $dir_loc : "$dir_loc:";
1120 $dir_name = ($p_dir eq '/' ? "/$dir_rel" : "$p_dir/$dir_rel");
1121 $dir_pref = "$dir_name/";
1122 $loc_pref = "$dir_loc/";
1124 if ( $byd_flag < 0 ) { # must be finddepth, report dirname now
1125 unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
1126 unless (chdir $updir_loc) { # $updir_loc (parent dir) is always untainted
1127 warnings::warnif "Can't cd to $updir_loc: $!\n";
1131 $fullname = $dir_loc; # $File::Find::fullname
1132 $name = $dir_name; # $File::Find::name
1134 if ($dir_rel eq ':') { # must be the top dir, where we started
1135 $name =~ s|:$||; # $File::Find::name
1136 $p_dir = "$p_dir:" unless ($p_dir =~ /:$/);
1138 $dir = $p_dir; # $File::Find::dir
1139 $_ = ($no_chdir ? $name : $dir_rel); # $_
1142 if ( substr($name,-2) eq '/.' ) {
1143 substr($name, length($name) == 2 ? -1 : -2) = ''; # $File::Find::name
1145 $dir = $p_dir; # $File::Find::dir
1146 $_ = ($no_chdir ? $dir_name : $dir_rel); # $_
1147 if ( substr($_,-2) eq '/.' ) {
1148 substr($_, length($_) == 2 ? -1 : -2) = '';
1152 lstat($_); # make sure file tests with '_' work
1153 { $wanted_callback->() }; # protect against wild "next"
1156 push @Stack,[$dir_loc, $updir_loc, $p_dir, $dir_rel,-1] if $bydepth;
1166 if ( ref($wanted) eq 'HASH' ) {
1167 if ( $wanted->{follow} || $wanted->{follow_fast}) {
1168 $wanted->{follow_skip} = 1 unless defined $wanted->{follow_skip};
1170 if ( $wanted->{untaint} ) {
1171 $wanted->{untaint_pattern} = $File::Find::untaint_pattern
1172 unless defined $wanted->{untaint_pattern};
1173 $wanted->{untaint_skip} = 0 unless defined $wanted->{untaint_skip};
1178 return { wanted => $wanted };
1184 _find_opt(wrap_wanted($wanted), @_);
1188 my $wanted = wrap_wanted(shift);
1189 $wanted->{bydepth} = 1;
1190 _find_opt($wanted, @_);
1194 $File::Find::skip_pattern = qr/^\.{1,2}\z/;
1195 $File::Find::untaint_pattern = qr|^([-+@\w./]+)$|;
1197 # These are hard-coded for now, but may move to hint files.
1200 $File::Find::dont_use_nlink = 1;
1202 elsif ($^O eq 'MacOS') {
1204 $File::Find::dont_use_nlink = 1;
1205 $File::Find::skip_pattern = qr/^Icon\015\z/;
1206 $File::Find::untaint_pattern = qr|^(.+)$|;
1209 # this _should_ work properly on all platforms
1210 # where File::Find can be expected to work
1211 $File::Find::current_dir = File::Spec->curdir || '.';
1213 $File::Find::dont_use_nlink = 1
1214 if $^O eq 'os2' || $^O eq 'dos' || $^O eq 'amigaos' || $^O eq 'MSWin32' ||
1215 $^O eq 'cygwin' || $^O eq 'epoc' || $^O eq 'qnx' ||
1218 # Set dont_use_nlink in your hint file if your system's stat doesn't
1219 # report the number of links in a directory as an indication
1220 # of the number of files.
1221 # See, e.g. hints/machten.sh for MachTen 2.2.
1222 unless ($File::Find::dont_use_nlink) {
1224 $File::Find::dont_use_nlink = 1 if ($Config::Config{'dont_use_nlink'});
1227 # We need a function that checks if a scalar is tainted. Either use the
1228 # Scalar::Util module's tainted() function or our (slower) pure Perl
1229 # fallback is_tainted_pp()
1232 eval { require Scalar::Util };
1233 *is_tainted = $@ ? \&is_tainted_pp : \&Scalar::Util::tainted;