-1

ディレクトリ ツリー (コマンド ライン引数で指定) の先頭から開始し、各サブディレクトリを再帰的に移動して、各ファイルに対して特定のアクションを実行する Perl スクリプトを作成したいと考えています。

私はfinddepthこれを使用していますが、ベースディレクトリから2レベル以上離れたディレクトリでスクリプトを実行すると機能しないようです。

これが私のコードです:

#!/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

コードにはいくつかの問題があります。

  • use warningsコマンドラインよりも望ましい-w

  • サブルーチンの先頭のブロックではなく、最初の使用ポイントで変数を宣言します

  • open、およびレキシカル ファイル ハンドルの 3 パラメータ形式を使用します。

  • 呼び出しのステータスを確認するときは、文字列openに組み込み変数を入れて、オープンが失敗した理由がわかるようにします。$!die

  • スカラー変数を二重引用符で囲まないでください。これはおそらく不要であり、状況によってはコードが壊れる可能性があります。やりたいことができる可能性は極めて低い

このプログラムの書き直しは、明示的なステートメントuse autodieの必要性を回避するために使用します。ファイルをコピーして元のファイルを上書きするのではなく、ファイルの名前を変更するためopen ... or die $!に使用します。rename

ファイル全体をメモリに読み込む代わりに、名前を変更したファイルを開いて 1 行ずつ読み込み、各行を編集して新しいファイルに書き込みます。

ドットで始まるファイルやドットで終わるファイルを無視するように書きました。そのとおりだと.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 に答える