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

我不太清楚您要做什么,但这与按名称中嵌入的日期对文件进行排序(并且可能删除?尽管您没有删除任何内容)有关。让我首先指出模块Time::Piece,它可以让您获得信息,localtime除了存储在一个方便的对象中。strptime此外,您可以使用类方法从格式化时间创建它们。

在下面的脚本中,我创建了一个数组引用数组,每个文件对应一个与模式匹配的文件。arrayref 的第一个元素是文件名,第二个元素是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 回答
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修饰符允许我们包含不匹配的空格以获得更好的格式。sub 可以被称为my @interesting = matching_files(7, \@files)(参见参考运算符\)。

获取和打印最多两天前的所有文件

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 回答
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);
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 回答