【问题标题】:directory was detected as file in perl目录在 perl 中被检测为文件
【发布时间】:2013-03-27 04:34:58
【问题描述】:

我尝试在循环中使用此条件(-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`;
}

【问题讨论】:

  • 这些符号链接是指向目录而不是实际目录吗?
  • 不,它是一个实际的目录。 :(
  • 整洁。什么类型的文件系统?你能给我们看看代码吗?
  • foreach 我的 $file (@files) { next if($file =~ m/^\./); if (-d $file and -e $file and !$seen{$file}) { $seen{$file} = 1;推@Dir, "$pwd/$file"; } 下一个 if ($file !~ m/\s/i);我的 $new_name = s/\s//g; mv $pwd/$file $pwd/$new_name; }
  • @files 数组的内容是什么?是来自glob 电话还是readdir 电话?

标签: linux perl file unix directory


【解决方案1】:

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

  • 你有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 的时间问题不在程序中,而在数据中。

【讨论】:

  • 当只需要 Perl 内置的 rename 函数时,使用 File::Copy 毫无意义。
  • 当。我忘了rename。我看到系统调用mv,说,嘿,你应该使用File::Copy。是的,在这种情况下(尤其是因为这是 Unix),rename 命令就可以了。
【解决方案2】:

这发生在我不久前编写一个类似的脚本。尝试使用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
} 

【讨论】:

    【解决方案3】:

    您的代码存在许多问题。为什么你认为-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 $!;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-05-28
      • 1970-01-01
      • 2018-07-23
      • 1970-01-01
      • 1970-01-01
      • 2011-12-04
      • 2013-10-27
      • 1970-01-01
      • 2010-10-12
      相关资源
      最近更新 更多