0

ここにスクリプトがあります

#!/usr/bin/perl
use strict;
use  warnings;
my($dayago, $prefix, $today_timestamp, $f,
   $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst,
   $daysago, $now, $old, @oldbackup);

opendir(DIR, "/home/ftpusr/backup/") || die("Error cannot open directory");

$now    = time();
$dayago = 3;

#($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($now-$dayago*60*60*24);
#$today_timestamp=sprintf("%4d%02d%02d",$year+1900,$mon+1,$mday);
#$old_timestamp=

$prefix = ".CATN0000.";

do {
    ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)
      = localtime($now - $dayago * 60 * 60 * 24);
    $today_timestamp = sprintf("%4d%02d%02d", $year + 1900, $mon + 1, $mday);
    while ($f = readdir(DIR)){
        if ( $f =~ /$prefix$today_timestamp/ ) {
            print "$f\n";
        }
    }
    $dayago -= 1;
    print "$dayago\n";
    print "$today_timestamp\n";
} until ($dayago == 0);
closedir(DIR);

ディレクトリ内のファイルは次のとおりです

-rw-r----- 1 db2inst1 db2grp1  184569856 2013-03-13 10:24 GSRTC.0.db2inst1.NODE0000.CATN0000.20130313102253.001
-rwxr-xr-x 1 db2inst1 db2grp1        259 2013-03-13 13:00 space_check.sh
-rw-r----- 1 db2inst1 db2grp1 1071665152 2013-03-14 10:06 AWDRT.0.db2inst1.NODE0000.CATN0000.20130314095856.001
-rw-r----- 1 db2inst1 db2grp1  184569856 2013-03-14 10:20 GSRTC.0.db2inst1.NODE0000.CATN0000.20130314101854.001
-rw-r--r-- 1 db2inst1 db2grp1          0 2013-03-14 13:49 bkp.sh
-rwxrwxrwx 1 db2inst1 db2grp1       1070 2013-03-14 20:12 awdrt_tabspc_report.sh
-rw-r----- 1 db2inst1 db2grp1 1085296640 2013-03-15 10:11 AWDRT.0.db2inst1.NODE0000.CATN0000.20130315100434.001
-rw-r----- 1 db2inst1 db2grp1  184569856 2013-03-15 10:30 GSRTC.0.db2inst1.NODE0000.CATN0000.20130315102900.001
-rw-r----- 1 db2inst1 db2grp1 1075859456 2013-03-16 12:16 AWDRT.0.db2inst1.NODE0000.CATN0000.20130316121043.001

スクリプトを実行すると、出力は次のようになります。

GSRTC.0.db2inst1.NODE0000.CATN0000.20130313102253.001
2
20130313
1
20130314
0
20130315

代わりに、次のファイルが必要です。

-rw-r----- 1 db2inst1 db2grp1 1071665152 2013-03-14 10:06 AWDRT.0.db2inst1.NODE0000.CATN0000.20130314095856.001
-rw-r----- 1 db2inst1 db2grp1  184569856 2013-03-14 10:20 GSRTC.0.db2inst1.NODE0000.CATN0000.20130314101854.001
-rw-r----- 1 db2inst1 db2grp1 1085296640 2013-03-15 10:11 AWDRT.0.db2inst1.NODE0000.CATN0000.20130315100434.001
-rw-r----- 1 db2inst1 db2grp1  184569856 2013-03-15 10:30 GSRTC.0.db2inst1.NODE0000.CATN0000.20130315102900.001

私が望むのは、最後のファイルを残し、古いバックアップを削除することだけです。助けていただければ幸いです。

4

3 に答える 3

1
  1. コードを理解していない場合は、できるだけ明確になるまで再フォーマットしてリファクタリングしてください。たとえば、詳細はループの意図を損なうだけなので、タイムスタンプ生成コードを別のサブルーチンに入れることができます。
  2. 変数を事前宣言しないでください。これは永続的ではなく、バグ ハントを困難にし、変装したグローバル変数です。むしろ、変数が使用される最も内側のスコープで変数を宣言 (およびすぐに初期化) します。
  3. ファイルまたはディレクトリ ハンドルとしてベアワードを使用しないでください。

実際の問題について:

  1. readdirリスト コンテキストで使用される関数は、そのディレクトリ内のすべての項目を返します。スカラー コンテキストで使用すると、次のエントリが返されるundefか、それ以上アイテムがない場合に返されます。これにより、イテレータになります。イテレータをリセットするには、ディレクトリを再度開く必要があります。すべての項目を配列に読み取ってから、特定のパターンに一致する項目を選択する方がよい場合があります。
  2. 正規表現では、ピリオド.はメタ文字であり、デフォルトで改行以外の文字に一致します。リテラルのドットに一致させるには、エスケープするか、引用符で囲む必要があり\Q...\Eます。

ここにあなたを助けるかもしれないいくつかのコードがあります:

指定されたタイムスタンプを計算するサブルーチン$days_ago:

{ # begin a enclosing scope for private variable
    my $now = time;
    my $secs_per_day = 24 * 60 * 60;

    sub timestamp {
      my ($ago) = @_;
      # we can use `undef` for vars we don't use
      my (undef, undef, undef, $mday, $mon, $year)
          = localtime( $now - $ago * $secs_per_year);
      return sprintf '%04d%02d%02d', $year + 1900, $mon + 1, $mday;
    }
}

ディレクトリ内のすべてのファイルを読み込む:

my $directory = '/foo/bar';
my @files = do {
  opendir my $dir, $directory or die "Can't open $directory: $!";
  readdir $dir;
};

これはdoブロックを使用します。レキシカルファイルハンドルまたはディレクトリハンドルは、スコープ外になると自動的に閉じられます。変数には、失敗の理由$!が含まれています。

一致するすべてのファイルを選択する:

sub matching_files {
    my ($days_ago, $files) = @_;
    my $timestamp = timestamp($days_ago)
    return grep /\Q .CATN0000. $timestamp \E/x, @$files;
}

これには数日前と、ファイル配列への参照が必要です。正規表現の/x修飾子を使用すると、一致しない空白を含めて、より適切な書式設定を行うことができます。サブルーチンは like で呼び出すことができますmy @interesting = matching_files(7, \@files)(参照演算子を参照してください\)。

2 日前までのすべてのファイルを取得して印刷する

for my $days_ago (reverse 0 .. 2) {
   my @interesting = matching_files($days_ago, \@files);
   print "Days ago: $days_ago\n";
   print "$_\n" foreach @interesting;
}

範囲演算子.. はシーケンスを作成し0, 1, 2、これを逆にします。のようなループ構造forは、末尾のステートメント修飾子として表示できます。インナーforeachは各アイテムを入れていき$_ます。

于 2013-03-16T14:24:37.860 に答える
1

あなたが何をしようとしているのかはよくわかりませんが、名前に埋め込まれた日付でファイルを並べ替える(そしておそらく何も削除しませんが、削除する)ことに関係があります。最初にモジュールTime::Pieceを指摘させてください。これによりlocaltime、便利なオブジェクトに保存されている以外の情報を取得できます。strptimeさらに、クラス メソッドを使用して、フォーマットされた時刻からそれらを作成できます。

以下のスクリプトでは、パターンに一致するファイルごとに 1 つずつ、配列参照の配列を作成します。arrayref の最初の要素はファイルの名前で、2 番目の要素は名前Time::Pieceの日付文字列の最初の 8 桁から作成されたオブジェクトです。また、今を表すオブジェも作ります。

#!/usr/bin/env perl

use strict;
use warnings;

use Time::Piece;

my $now = localtime();

my $prefix = "CATN0000";
opendir(my $dir, "/home/ftpusr/backup/") || die("Error cannot open directory: $!");

my @files;
while ( my $file = readdir $dir ) {
  $file =~ /\.$prefix\.(\d{8})\d*\.\d{3}/ or next;
  push @files, [ $file, Time::Piece->strptime( $1, '%Y%m%d') ];
}

この開始点から、Time::Pieceオブジェクトを比較して並べ替え、それらをオブジェクトと比較し$now、結果としてファイルに対して必要なことを行うことができます。

于 2013-03-16T14:21:57.810 に答える
0

Yoこれは私のために働いた........

#!/usr/bin/perl
use strict;
use warnings;


my($dayago,$prefix,$today_timestamp,$f,$sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst,$daysago,$now,$old,@oldbackup);
#opendir(DIR, "/home/ftpusr/backup/") || die("Error cannot open directory");
$now=time();
$dayago=3;
#($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($now-$dayago*60*60*24);
#$today_timestamp=sprintf("%4d%02d%02d",$year+1900,$mon+1,$mday);
#$old_timestamp=
$prefix = ".CATN0000.";
do {
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($now-$dayago*60*60*24);
opendir(DIR, "/home/ftpusr/backup/") || die("Error cannot open directory");
$today_timestamp=sprintf("%4d%02d%02d",$year+1900,$mon+1,$mday);
while ($f = readdir(DIR)){
  if ( $f =~ /$prefix$today_timestamp/ ) {
        print "$f\n";
        }
}
$dayago -= 1;
print "$dayago\n";
print "$today_timestamp\n";
}until ($dayago == 0);
closedir(DIR);

より良い解決策?????????

于 2013-03-16T10:38:23.213 に答える