-1

我想编写一个 Perl 脚本,它从目录树的顶部开始(在命令行参数中提供)并递归地遍历每个子目录,对每个文件执行特定操作。

我正在使用finddepth它,但是当我在距离基本目录两级或更高级别的目录上运行脚本时,它似乎不起作用。

这是我的代码:

#!/usr/local/bin/perl -w

use strict;

use File::Copy;
use File::Find;
use File::Basename;
use File::Path;

finddepth(\&file_list, @ARGV);

sub file_list {

    my ($file_path, $name, $path, $suffix);

    $file_path = $File::Find::name;

    ($name, $path, $suffix) = fileparse($file_path, /\.*/);

    my $fullname = $name . $suffix;
    my $file = $fullname;

    if ($file =~ /^[^\.].*[^\.pl]$/) {

        copy($file, "$file.orig");

        open(FILE, "$file");
        my @file_data = <FILE>;
        close(FILE);

        open(FOUT, ">$file") or die " \n File cannot be opened !";

        foreach my $line (@file_data) {
            if ($line =~ /^\s+Error:/) {
                $line =~ s/([^-]\d+)/ \*\*/gc;
                print FOUT $line;
            }
            else {
                print FOUT $line;
            }
        }
        close(FOUT);
    }
}

始终抛出以下警告/错误:

  1. 读取关闭的文件句柄
  2. 文件打不开!

我似乎无法弄清楚为什么会这样。我试图让我的问题尽可能具体。如果您需要更多信息,请告诉我。谢谢你。

4

2 回答 2

1

您无法打开该文件,因为当时$file恰好是一个目录,因此您需要为此添加一个检查。

or die在打开文件进行阅读时,可能值得添加一条语句。

另请注意,File::Find设置$_为当前文件名,因此您生成的 5 行$file实际上是不必要的。

于 2013-02-12T06:17:03.007 回答
1

您的代码存在一些问题。

  • use warnings比命令行更可取-w

  • 在第一个使用点声明变量,而不是在子例程顶部的块中

  • open使用, 和词法文件句柄的三参数形式

  • 检查open调用状态时,将内置变量$!放入die字符串中,以便知道打开失败的原因

  • 不要将标量变量放在双引号内。这可能是不必要的,并且在某些情况下可能会破坏您的代码。极不可能做任何你想做的事

程序的这种重写use autodie用于避免显式open ... or die $!语句的需要。它用于rename更改文件的名称,而不是复制它并覆盖原始文件。

我没有将整个文件读入内存,而是打开重命名的文件并逐行读取,编辑每一行并将其写入新文件

我已经编写了它,以便它忽略以点开头或结尾的文件.pl- 我希望这是对的。我也非常怀疑您的替换s/[^-]\d+/ **/g,它查找前面不是连字符的字符的数字序列;那正确吗?

#!/usr/local/bin/perl

use strict;
use warnings;

use autodie;
no autodie 'unlink';

use File::Find 'finddepth';

finddepth(\&file_list, @ARGV);

sub file_list {

  return unless -f;
  return if /^\./ or /\.pl$/;

  my $file = $_;
  my $orig = "$file.orig";

  unlink $orig;
  rename $file, $orig;

  open my $infh, '<', $orig;
  open my $outfh, '>', $file;

  while (my $line = <$infh>) {
    if ($line =~ /^\s+Error:/) {
      $line =~ s/[^-]\d+/ **/g
    }
    print $outfh $line;
  }

  close $outfh;
}
于 2013-02-12T08:44:37.483 回答