目录在perl中被检测为文件

时间:2013-04-04 21:55:06

标签: linux perl file unix directory

我尝试在循环中使用此条件(-d $var)来检查给定目录中有多少个子目录,但是某些文件夹被检测为文件。无法识别目录的情况怎么了?我该如何解决这个问题?

我的代码是:

foreach my $file (@files) {
    next if($file =~ m/^\./);
    if (-d $file and -e $file and !$seen{$file}) {
        $seen{$file} = 1;
        push @Dir, "$pwd/$file";
    }
    next if ($file !~ m/\s/i);
    my $new_name = s/\s//g;
    `mv $pwd/$file $pwd/$new_name`;
}

3 个答案:

答案 0 :(得分:2)

我没有看到任何明显的东西。但是,我确实发现了一个错误。

  • 您有my $new_name = s/\s//g;。您有=而不是=~
  • 您也没有说明如何获得$new_name进行替换。

这些都不是你自己的问题。

另一种可能性是你使用三种不同的测试。我想知道你是否以某种方式遇到-d通过的情况,但其他条件不正确。你可能想把它们分开。

我还注意到您测试该文件是否是$file的目录,但是当您将目录名放入@Dir数组时,请将其添加到$pwd前面。这里发生了什么?你还需要做if ( -d "$pwd/$file" )吗?

我建议您输入一些调试语句,以查看您遇到问题的位置。

试试这个:

use strict;
use warnings;

use feature qw(say);
use File::Copy;

my %seen;
my @dir;
for my $file ( @files ) {
    say qq(DEBUG: Looking at "$file");
    next if $seen{$file};
    say qq(DEBUG: "$file" has not been previously seen);
    $seen{$file} = 1;
    next if $file =~ /^\./;
    say qq(DEBUG: "$file" does not start with a period);
    if ( -d $file ) {
       say qq(DEBUG: "$file" is a directory);
       push @dir, "$pwd/$file;
    }
    else { #DEBUG:
       say qq(DEBUG: "$file" is a file);
   } #DEBUG:
   my $new_name = $file;
   if ( $new_name =~ s/\s+//g ) {
      say qq(DEBUG: Moving file "$file" to "$new_name");
      move $file, $new_name or
        die qq(Couldn't move "$file" to "$new_name");
   }
}
  • use feature qw(say);允许您使用say命令。这与print类似,只不过它为您添加了一条新行。
  • use File::Copy模块允许您使用move语句。没有更多的炮轰和依赖操作系统。 Perl附带了一整套模块,让您的生活更轻松。例如,File::Find允许您查找文件和目录。
  • 我在%seen中包含所有文件和目录(为什么不呢?)并在检查它是否是目录之前先检查一下。
  • 我使用move $file, $new_name or die qq(...)查看该移动声明是否有效。您应该始终测试函数的输出 - 特别是失败的函数,如移动文件名或复制它等等。
  • 请注意我if ( $new_name =~ s/\s+//g )。这允许我测试$new_name是否有空格并同时删除这些空格。
  • qq(...)就像双引号,但你可以在字符串中使用引号,而不必反引用它们。这样,我可以看到我的文件名在名称的末尾是否有空格或NL。

使代码生效后,您可以轻松搜索字符串DEBUG:并删除噪音。

我还没有测试过我的代码(当程序没有真正完成并且我不知道你的数据是什么时很难),但我希望你能得到这个想法。 DEBUG:语句可让您查看代码中发生的更多信息,并帮助您找到逻辑问题。大约1/2时间问题不在程序中,而是在数据中。

答案 1 :(得分:1)

这件事发生在我身上一段时间后,写了一个类似于此的脚本。尝试使用File::Spec方法catfile使用整个路径。我假设您在与实际文件和目录不同的目录中运行它。

use Cwd;
use File::Spec;

my $dir = getcwd; # Or whatever directory name you want
my $full_name = File::Spec->catfile($dir, $file);
if (-d $full_name) {
  # Do something
} 

答案 2 :(得分:1)

您的代码存在许多问题。为什么你认为-d测试失败了?同名重命名适用于目录和文件;唯一的区别是,第一次看到目录时,目录会被另外推送到@dir数组。

我不清楚您想要做什么,但此版本仅重命名名称中包含空格字符的文件。

foreach my $file (@files) {

    next if $file =~ m/^\./;

    if (-d $file ) {
        push @dir, "$pwd/$file" unless $seen{$file}++;
        next;
    }

    my $new_name = $file;
    if ($new_name =~ s/\s//g) {
        rename "$pwd/$file", "$pwd/$new_name" or warn $!;
    }
}