Re: Not OK: perl v5.9.0 +DEVEL17881 on i386-freebsd 4.6-release (UNINSTALLED)
[p5sagit/p5-mst-13.2.git] / lib / File / Find.pm
index 7bcd270..72fd195 100644 (file)
@@ -2,24 +2,23 @@ package File::Find;
 use 5.006;
 use strict;
 use warnings;
-our $VERSION = '1.03';
+use warnings::register;
+our $VERSION = '1.04';
 require Exporter;
 require Cwd;
 
 =head1 NAME
 
-find - traverse a file tree
-
-finddepth - traverse a directory structure depth-first
+File::Find - Traverse a directory tree.
 
 =head1 SYNOPSIS
 
     use File::Find;
-    find(\&wanted, '/foo', '/bar');
+    find(\&wanted, @directories_to_seach);
     sub wanted { ... }
 
     use File::Find;
-    finddepth(\&wanted, '/foo', '/bar');
+    finddepth(\&wanted, @directories_to_search);
     sub wanted { ... }
 
     use File::Find;
@@ -27,8 +26,40 @@ finddepth - traverse a directory structure depth-first
 
 =head1 DESCRIPTION
 
+These are functions for searching through directory trees doing work
+on each file found similar to the Unix I<find> command.  File::Find
+exports two functions, C<find> and C<finddepth>.  They work similarly
+but have subtle differences.
+
+=over 4
+
+=item B<find>
+
+  find(\&wanted,  @directories);
+  find(\%options, @directories);
+
+find() does a breadth-first search over the given @directories in the
+order they are given.  In essense, it works from the top down.
+
+For each file or directory found the &wanted subroutine is called (see
+below for details).  Additionally, for each directory found it will go
+into that directory and continue the search.
+
+=item B<finddepth>
+
+  finddepth(\&wanted,  @directories);
+  finddepth(\%options, @directories);
+
+finddepth() works just like find() except it does a depth-first search.
+It works from the bottom of the directory tree up.
+
+=back
+
+=head2 %options
+
 The first argument to find() is either a hash reference describing the
-operations to be performed for each file, or a code reference.
+operations to be performed for each file, or a code reference.  The
+code reference is described in L<The wanted function> below.
 
 Here are the possible keys for the hash:
 
@@ -36,14 +67,14 @@ Here are the possible keys for the hash:
 
 =item C<wanted>
 
-The value should be a code reference.  This code reference is called
-I<the wanted() function> below.
+The value should be a code reference.  This code reference is
+described in L<The wanted function> below.
 
 =item C<bydepth>
 
 Reports the name of a directory only AFTER all its entries
 have been reported.  Entry point finddepth() is a shortcut for
-specifying C<{ bydepth => 1 }> in the first argument of find().
+specifying C<{ bydepth =E<gt> 1 }> in the first argument of find().
 
 =item C<preprocess>
 
@@ -144,12 +175,48 @@ including all its sub-directories. The default is to 'die' in such a case.
 
 =back
 
-The wanted() function does whatever verifications you want.
-C<$File::Find::dir> contains the current directory name, and C<$_> the
-current filename within that directory.  C<$File::Find::name> contains
-the complete pathname to the file. You are chdir()'d to
-C<$File::Find::dir> when the function is called, unless C<no_chdir>
-was specified.  When C<follow> or C<follow_fast> are in effect, there is
+=head2 The wanted function
+
+The wanted() function does whatever verifications you want on each
+file and directory.  It takes no arguments but rather does its work
+through a collection of variables.
+
+=over 4
+
+=item C<$File::Find::dir> is the current directory name,
+
+=item C<$_> is the current filename within that directory
+
+=item C<$File::Find::name> is the complete pathname to the file.
+
+=back
+
+Don't modify these variables.
+
+For example, when examining the file /some/path/foo.ext you will have:
+
+    $File::Find::dir  = /some/path/
+    $_                = foo.ext
+    $File::Find::name = /some/path/foo.ext
+
+You are chdir()'d toC<$File::Find::dir> when the function is called,
+unless C<no_chdir> was specified. Note that when changing to
+directories is in effect the root directory (F</>) is a somewhat
+special case inasmuch as the concatenation of C<$File::Find::dir>,
+C<'/'> and C<$_> is not literally equal to C<$File::Find::name>. The
+table below summarizes all variants:
+
+              $File::Find::name  $File::Find::dir  $_
+ default      /                  /                 .
+ no_chdir=>0  /etc               /                 etc
+              /etc/x             /etc              x
+
+ no_chdir=>1  /                  /                 /
+              /etc               /                 /etc
+              /etc/x             /etc              /etc/x
+
+
+When <follow> or <follow_fast> are in effect, there is
 also a C<$File::Find::fullname>.  The function may set
 C<$File::Find::prune> to prune the tree unless C<bydepth> was
 specified.  Unless C<follow> or C<follow_fast> is specified, for
@@ -190,6 +257,17 @@ links that don't resolve:
 See also the script C<pfind> on CPAN for a nice application of this
 module.
 
+=head1 WARNINGS
+
+If you run your program with the C<-w> switch, or if you use the
+C<warnings> pragma, File::Find will report warnings for several weird
+situations. You can disable these warnings by putting the statement
+
+    no warnings 'File::Find';
+
+in the appropriate scope. See L<perllexwarn> for more info about lexical
+warnings.
+
 =head1 CAVEAT
 
 =over 2
@@ -197,15 +275,16 @@ module.
 =item $dont_use_nlink
 
 You can set the variable C<$File::Find::dont_use_nlink> to 1, if you want to
-force File::Find to always stat directories. This was used for systems
-that do not have the correct C<nlink> count for directories. Examples are
-ISO-9660 (CD-R), AFS, and operating systems like OS/2, DOS and a couple of
-others.
+force File::Find to always stat directories. This was used for file systems
+that do not have an C<nlink> count matching the number of sub-directories.
+Examples are ISO-9660 (CD-ROM), AFS, HPFS (OS/2 file system), FAT (DOS file
+system) and a couple of others.
 
-Since now File::Find should now detect such things on-the-fly and switch it
-self to using stat, this will probably not a problem to you.
+You shouldn't need to set this variable, since File::Find should now detect
+such file systems on-the-fly and switch itself to using stat. This works even
+for parts of your file system, like a mounted CD-ROM.
 
-If you do set $dont_use_nlink to 1, you will notice slow-downs.
+If you do set C<$File::Find::dont_use_nlink> to 1, you will notice slow-downs.
 
 =item symlinks
 
@@ -452,7 +531,7 @@ sub Follow_SymLink($) {
        return undef unless defined $DEV;  #  dangling symbolic link
     }
 
-    if ($full_check && $SLnkSeen{$DEV, $INO}++) {
+    if ($full_check && defined $DEV && $SLnkSeen{$DEV, $INO}++) {
        if ( ($follow_skip < 1) || ((-d _) && ($follow_skip < 2)) ) {
            die "$AbsName encountered a second time";
        }
@@ -542,7 +621,7 @@ sub _find_opt {
                else {
                    $abs_dir = contract_name_Mac($cwd, $top_item);
                    unless (defined $abs_dir) {
-                       warn "Can't determine absolute path for $top_item (No such file or directory)\n" if $^W;
+                       warnings::warnif "Can't determine absolute path for $top_item (No such file or directory)\n";
                        next Proc_Top_Item;
                    }
                }
@@ -565,7 +644,7 @@ sub _find_opt {
                    if (ref $dangling_symlinks eq 'CODE') {
                        $dangling_symlinks->($top_item, $cwd);
                    } else {
-                       warn "$top_item is a dangling symbolic link\n" if $^W;
+                       warnings::warnif "$top_item is a dangling symbolic link\n";
                    }
                }
                next Proc_Top_Item;
@@ -579,7 +658,7 @@ sub _find_opt {
        else { # no follow
            $topdir = $top_item;
            unless (defined $topnlink) {
-               warn "Can't stat $top_item: $!\n" if $^W;
+               warnings::warnif "Can't stat $top_item: $!\n";
                next Proc_Top_Item;
            }
            if (-d _) {
@@ -616,13 +695,13 @@ sub _find_opt {
            }
 
            unless ($no_chdir || chdir $abs_dir) {
-               warn "Couldn't chdir $abs_dir: $!\n" if $^W;
+               warnings::warnif "Couldn't chdir $abs_dir: $!\n";
                next Proc_Top_Item;
            }
 
            $name = $abs_dir . $_; # $File::Find::name
 
-           { &$wanted_callback }; # protect against wild "next"
+           { $wanted_callback->() }; # protect against wild "next"
 
        }
 
@@ -684,7 +763,7 @@ sub _find_dir($$$) {
            }
        }
        unless (chdir $udir) {
-           warn "Can't cd to $udir: $!\n" if $^W;
+           warnings::warnif "Can't cd to $udir: $!\n";
            return;
        }
     }
@@ -703,7 +782,7 @@ sub _find_dir($$$) {
            $_= ($no_chdir ? $dir_name : $dir_rel ); # $_
            # prune may happen here
            $prune= 0;
-           { &$wanted_callback };      # protect against wild "next"
+           { $wanted_callback->() };   # protect against wild "next"
            next if $prune;
        }
 
@@ -727,10 +806,11 @@ sub _find_dir($$$) {
            }
            unless (chdir $udir) {
                if ($Is_MacOS) {
-                   warn "Can't cd to ($p_dir) $udir: $!\n" if $^W;
+                   warnings::warnif "Can't cd to ($p_dir) $udir: $!\n";
                }
                else {
-                   warn "Can't cd to (" . ($p_dir ne '/' ? $p_dir : '') . "/) $udir: $!\n" if $^W;
+                   warnings::warnif "Can't cd to (" .
+                       ($p_dir ne '/' ? $p_dir : '') . "/) $udir: $!\n";
                }
                next;
            }
@@ -745,12 +825,12 @@ sub _find_dir($$$) {
 
        # Get the list of files in the current directory.
        unless (opendir DIR, ($no_chdir ? $dir_name : $File::Find::current_dir)) {
-           warn "Can't opendir($dir_name): $!\n" if $^W;
+           warnings::warnif "Can't opendir($dir_name): $!\n";
            next;
        }
        @filenames = readdir DIR;
        closedir(DIR);
-       @filenames = &$pre_process(@filenames) if $pre_process;
+       @filenames = $pre_process->(@filenames) if $pre_process;
        push @Stack,[$CdLvl,$dir_name,"",-2]   if $post_process;
 
        # default: use whatever was specifid
@@ -766,7 +846,7 @@ sub _find_dir($$$) {
                
                $name = $dir_pref . $FN; # $File::Find::name
                $_ = ($no_chdir ? $name : $FN); # $_
-               { &$wanted_callback }; # protect against wild "next"
+               { $wanted_callback->() }; # protect against wild "next"
            }
 
        }
@@ -790,13 +870,13 @@ sub _find_dir($$$) {
                    else {
                        $name = $dir_pref . $FN; # $File::Find::name
                        $_= ($no_chdir ? $name : $FN); # $_
-                       { &$wanted_callback }; # protect against wild "next"
+                       { $wanted_callback->() }; # protect against wild "next"
                    }
                }
                else {
                    $name = $dir_pref . $FN; # $File::Find::name
                    $_= ($no_chdir ? $name : $FN); # $_
-                   { &$wanted_callback }; # protect against wild "next"
+                   { $wanted_callback->() }; # protect against wild "next"
                }
            }
        }
@@ -831,7 +911,7 @@ sub _find_dir($$$) {
            if ( $nlink == -2 ) {
                $name = $dir = $p_dir; # $File::Find::name / dir
                 $_ = $File::Find::current_dir;
-               &$post_process;         # End-of-directory processing
+               $post_process->();              # End-of-directory processing
            }
            elsif ( $nlink < 0 ) {  # must be finddepth, report dirname now
                $name = $dir_name;
@@ -845,15 +925,15 @@ sub _find_dir($$$) {
                }
                else {
                    if ( substr($name,-2) eq '/.' ) {
-                       $name =~ s|/\.$||;
+                       substr($name, length($name) == 2 ? -1 : -2) = '';
                    }
                    $dir = $p_dir;
                    $_ = ($no_chdir ? $dir_name : $dir_rel );
                    if ( substr($_,-2) eq '/.' ) {
-                       s|/\.$||;
+                       substr($_, length($_) == 2 ? -1 : -2) = '';
                    }
                }
-               { &$wanted_callback }; # protect against wild "next"
+               { $wanted_callback->() }; # protect against wild "next"
             }
             else {
                push @Stack,[$CdLvl,$p_dir,$dir_rel,-1]  if  $bydepth;
@@ -914,7 +994,7 @@ sub _find_dir_symlnk($$$) {
        }
        $ok = chdir($updir_loc) unless ($p_dir eq $File::Find::current_dir);
        unless ($ok) {
-           warn "Can't cd to $updir_loc: $!\n" if $^W;
+           warnings::warnif "Can't cd to $updir_loc: $!\n";
            return;
        }
     }
@@ -931,7 +1011,7 @@ sub _find_dir_symlnk($$$) {
            # change (back) to parent directory (always untainted)
            unless ($no_chdir) {
                unless (chdir $updir_loc) {
-                   warn "Can't cd to $updir_loc: $!\n" if $^W;
+                   warnings::warnif "Can't cd to $updir_loc: $!\n";
                    next;
                }
            }
@@ -942,7 +1022,7 @@ sub _find_dir_symlnk($$$) {
            # prune may happen here
            $prune= 0;
            lstat($_); # make sure  file tests with '_' work
-           { &$wanted_callback }; # protect against wild "next"
+           { $wanted_callback->() }; # protect against wild "next"
            next if $prune;
        }
 
@@ -962,7 +1042,7 @@ sub _find_dir_symlnk($$$) {
                }
            }
            unless (chdir $updir_loc) {
-               warn "Can't cd to $updir_loc: $!\n" if $^W;
+               warnings::warnif "Can't cd to $updir_loc: $!\n";
                next;
            }
        }
@@ -975,7 +1055,7 @@ sub _find_dir_symlnk($$$) {
 
        # Get the list of files in the current directory.
        unless (opendir DIR, ($no_chdir ? $dir_loc : $File::Find::current_dir)) {
-           warn "Can't opendir($dir_loc): $!\n" if $^W;
+           warnings::warnif "Can't opendir($dir_loc): $!\n";
            next;
        }
        @filenames = readdir DIR;
@@ -997,7 +1077,7 @@ sub _find_dir_symlnk($$$) {
                $fullname = $new_loc; # $File::Find::fullname 
                $name = $dir_pref . $FN; # $File::Find::name
                $_ = ($no_chdir ? $name : $FN); # $_
-               { &$wanted_callback }; # protect against wild "next"
+               { $wanted_callback->() }; # protect against wild "next"
            }
        }
 
@@ -1020,7 +1100,7 @@ sub _find_dir_symlnk($$$) {
            if ( $byd_flag < 0 ) {  # must be finddepth, report dirname now
                unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
                    unless (chdir $updir_loc) { # $updir_loc (parent dir) is always untainted 
-                       warn "Can't cd to $updir_loc: $!\n" if $^W;
+                       warnings::warnif "Can't cd to $updir_loc: $!\n";
                        next;
                    }
                }
@@ -1036,17 +1116,17 @@ sub _find_dir_symlnk($$$) {
                }
                else {
                    if ( substr($name,-2) eq '/.' ) {
-                       $name =~ s|/\.$||; # $File::Find::name
+                       substr($name, length($name) == 2 ? -1 : -2) = ''; # $File::Find::name
                    }
                    $dir = $p_dir; # $File::Find::dir
                    $_ = ($no_chdir ? $dir_name : $dir_rel); # $_
                    if ( substr($_,-2) eq '/.' ) {
-                       s|/\.$||;
+                       substr($_, length($_) == 2 ? -1 : -2) = '';
                    }
                }
 
                lstat($_); # make sure file tests with '_' work
-               { &$wanted_callback }; # protect against wild "next"
+               { $wanted_callback->() }; # protect against wild "next"
            }
            else {
                push @Stack,[$dir_loc, $updir_loc, $p_dir, $dir_rel,-1]  if  $bydepth;
@@ -1108,7 +1188,8 @@ $File::Find::current_dir = File::Spec->curdir || '.';
 
 $File::Find::dont_use_nlink = 1
     if $^O eq 'os2' || $^O eq 'dos' || $^O eq 'amigaos' || $^O eq 'MSWin32' ||
-       $^O eq 'cygwin' || $^O eq 'epoc' || $^O eq 'NetWare';
+       $^O eq 'cygwin' || $^O eq 'epoc' || $^O eq 'qnx' ||
+          $^O eq 'nto';
 
 # Set dont_use_nlink in your hint file if your system's stat doesn't
 # report the number of links in a directory as an indication