2

我尝试(-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`;
}
4

3 回答 3

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(...)来查看该 move 语句是否有效。您应该始终测试函数的输出——尤其是容易失败的函数,例如移动文件名或复制文件等。
  • 注意我做if ( $new_name =~ s/\s+//g )。这使我可以测试是否$new_name有空间并同时删除这些空间。
  • 就像双qq(...)引号,但您可以在字符串中使用引号而无需反引号。这样,我可以查看我的文件名是否在名称末尾有空格或 NL。

一旦你的代码工作,你可以轻松地搜索字符串DEBUG:并消除噪音。

我还没有测试我的代码(当程序没有真正完成并且我不知道你的数据是什么样子时很难),但我希望你能明白。这些DEBUG:语句将允许您查看代码中发生的更多内容并帮助您找到逻辑问题。大约 1/2 的时间问题不在程序中,而在数据中。

于 2013-04-04T22:48:50.330 回答
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
} 
于 2013-04-04T22:21:12.923 回答
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 $!;
    }
}
于 2013-04-05T00:47:27.083 回答