use strict;
use warnings;
use warnings::register;
-our $VERSION = '1.10';
+our $VERSION = '1.12';
require Exporter;
require Cwd;
finddepth(\&wanted, @directories);
finddepth(\%options, @directories);
-C<finddepth()> works just like C<find()> except that is invokes the
+C<finddepth()> works just like C<find()> except that it invokes the
C<&wanted> function for a directory I<after> invoking it for the
directory's contents. It does a postorder traversal instead of a
preorder traversal, working from the bottom of the directory tree up
=item *
-Previous versions of File::Find were guaranteed to call an I<lstat>
-before the user's C<wanted()> function was called, but this is no
-longer the case. Since this depends on C<$File::Find::dont_use_nlink>, $^O,
-and other factors, fast file checks involving C<_> are not recommended
-unless C<wanted()> calls I<lstat> first.
+It is guaranteed that an I<lstat> has been called before the user's
+C<wanted()> function is called. This enables fast file checks involving S<_>.
+Note that this guarantee no longer holds if I<follow> or I<follow_fast>
+are not set.
=item *
=back
-Don't modify these variables.
+The above variables have all been localized and may be changed without
+effecting data outside of the wanted function.
For example, when examining the file F</some/path/foo.ext> you will have:
local *_ = \my $a;
my $cwd = $wanted->{bydepth} ? Cwd::fastcwd() : Cwd::getcwd();
+ if ($Is_VMS) {
+ # VMS returns this by default in VMS format which just doesn't
+ # work for the rest of this module.
+ $cwd = VMS::Filespec::unixpath($cwd);
+
+ # Apparently this is not expected to have a trailing space.
+ # To attempt to make VMS/UNIX conversions mostly reversable,
+ # a trailing slash is needed. The run-time functions ignore the
+ # resulting double slash, but it causes the perl tests to fail.
+ $cwd =~ s#/\z##;
+
+ # This comes up in upper case now, but should be lower.
+ # In the future this could be exact case, no need to change.
+ }
my $cwd_untainted = $cwd;
my $check_t_cwd = 1;
$wanted_callback = $wanted->{wanted};
$abs_dir = $cwd;
}
else { # care about any ../
+ $top_item =~ s/\.dir\z//i if $Is_VMS;
$abs_dir = contract_name("$cwd/",$top_item);
}
}
}
if (-d _) {
+ $top_item =~ s/\.dir\z//i if $Is_VMS;
_find_dir_symlnk($wanted, $abs_dir, $top_item);
$Is_Dir= 1;
}
$dir_pref= ($p_dir =~ /:$/) ? $p_dir : "$p_dir:"; # preface
} elsif ($^O eq 'MSWin32') {
$dir_pref = ($p_dir =~ m|\w:/$| ? $p_dir : "$p_dir/" );
+ } elsif ($^O eq 'VMS') {
+
+ # VMS is returning trailing .dir on directories
+ # and trailing . on files and symbolic links
+ # in UNIX syntax.
+ #
+
+ $p_dir =~ s/\.(dir)?$//i unless $p_dir eq '.';
+
+ $dir_pref = ($p_dir =~ m/[\]>]+$/ ? $p_dir : "$p_dir/" );
}
else {
$dir_pref= ( $p_dir eq '/' ? '/' : "$p_dir/" );
if ($nlink == 2 && !$no_nlink) {
# This dir has no subdirectories.
for my $FN (@filenames) {
+ if ($Is_VMS) {
+ # Big hammer here - Compensate for VMS trailing . and .dir
+ # No win situation until this is changed, but this
+ # will handle the majority of the cases with breaking the fewest
+
+ $FN =~ s/\.dir\z//i;
+ $FN =~ s#\.$## if ($FN ne '.');
+ }
next if $FN =~ $File::Find::skip_pattern;
$name = $dir_pref . $FN; # $File::Find::name
if ($Is_MacOS) {
$tmp = (':' x ($CdLvl-$Level)) . ':';
}
+ elsif ($Is_VMS) {
+ $tmp = '[' . ('-' x ($CdLvl-$Level)) . ']';
+ }
else {
$tmp = join('/',('..') x ($CdLvl-$Level));
}
- die "Can't cd to $dir_name" . $tmp
+ die "Can't cd to $tmp from $dir_name"
unless chdir ($tmp);
$CdLvl = $Level;
}
$dir_name = ($p_dir =~ m|\w:/$| ? "$p_dir$dir_rel" : "$p_dir/$dir_rel");
$dir_pref = "$dir_name/";
}
+ elsif ($^O eq 'VMS') {
+ if ($p_dir =~ m/[\]>]+$/) {
+ $dir_name = $p_dir;
+ $dir_name =~ s/([\]>]+)$/.$dir_rel$1/;
+ $dir_pref = $dir_name;
+ }
+ else {
+ $dir_name = "$p_dir/$dir_rel";
+ $dir_pref = "$dir_name/";
+ }
+ }
else {
$dir_name = ($p_dir eq '/' ? "/$dir_rel" : "$p_dir/$dir_rel");
$dir_pref = "$dir_name/";
closedir(DIR);
for my $FN (@filenames) {
+ if ($Is_VMS) {
+ # Big hammer here - Compensate for VMS trailing . and .dir
+ # No win situation until this is changed, but this
+ # will handle the majority of the cases with breaking the fewest.
+
+ $FN =~ s/\.dir\z//i;
+ $FN =~ s#\.$## if ($FN ne '.');
+ }
next if $FN =~ $File::Find::skip_pattern;
# follow symbolic links / do an lstat
# ignore if invalid symlink
unless (defined $new_loc) {
- if ($dangling_symlinks) {
+ if (!defined -l _ && $dangling_symlinks) {
if (ref $dangling_symlinks eq 'CODE') {
$dangling_symlinks->($FN, $dir_pref);
} else {
}
if (-d _) {
+ if ($Is_VMS) {
+ $FN =~ s/\.dir\z//i;
+ $FN =~ s#\.$## if ($FN ne '.');
+ $new_loc =~ s/\.dir\z//i;
+ $new_loc =~ s#\.$## if ($new_loc ne '.');
+ }
push @Stack,[$new_loc,$updir_loc,$dir_name,$FN,1];
}
else {