在perl脚本中添加更多功能

时间:2011-07-19 16:25:58

标签: perl

在下面的perl脚本中,我用当前日期检查我的文件夹名称(日期格式如11-08-31)。如果匹配,我处理该文件夹。如果今天的日期没有文件夹,它还会检查前一天的文件夹。我已经在这里提出了这类问题,但我需要在这里进行一些更改并添加新功能:

  • 如果今天找不到,脚本会检查上一个日期。但我需要检查之前的日期是否已经处理过,以便我不再处理它。那么,我是否需要为它创建一个列表?

  • 此脚本仅检查上一个日期。如果我必须检查前两天怎么办?谢谢你的帮助。希望你理解我的疑惑。

更新:此perl脚本在使用文件夹名称检查curent日期时自动运行。该文件夹是一个tar文件夹,从其他服务器加载。

所以,基本上我需要运行脚本,如果它与文件夹名称和当前日期匹配。

问题:有时,我曾经在第二天获取该文件夹,而我的perl脚本仅检查当前日期。我得到的文件夹的名称是前一个日期(不是当前日期)。所以,我需要手动处理文件夹。我需要在我的perl脚本中自动化它


#!/usr/bin/perl
use strict;
use warnings;
use Cwd;
use DateTime;
use File::Copy;

# set to your desired time zone
my $today = DateTime->now( time_zone => "America/New_York" );
my $td = $today->strftime("%y-%m-%d");

# strongly recommended to do date math in the 'floating'/UTC zone
my $yesterday = $today->set_time_zone('floating')->subtract( days => 1);
my $yd = $yesterday->set_time_zone('America/New_York')->strftime("%y-%m-%d");

my $dir = shift or die "Provide path on command line. $!";

if ($dir eq '.') {
    $dir = cwd;
}
elsif ($dir !~ /^\//) {
    $dir = cwd() . "/$dir"; 
}

opendir my $dh, $dir or die $!;
my @dir = sort grep {-d and /$td/ || /$yd/} readdir $dh;
closedir $dh or die $!;
@dir or die "Found no date directories. $!";

my $dday = "$dir/$dir[-1]"; # is today unless today not found, then yesterday
my $fdir = '/some/example/path/';    
my @gzfiles = glob("$dday/*tar.gz");

foreach my $zf (@gzfiles) {  
    next if (($zf =~ /BMP/) || ($zf =~ /LG/) || ($zf =~ /MAP/) || ($zf =~ /STR/)); 
    print "$zf\n";
    copy($zf, $fdir) or die "Unable to copy. $!";
}

3 个答案:

答案 0 :(得分:0)

如果要保持这些目录是否在应用程序的单次运行之后处理的状态,您可以在每个目录中创建一个.processed文件,并在处理目录之前检查是否存在此文件。

如果您只需要在执行脚本期间存储这些目录的状态(已处理或未处理),则可以使用以目录名称键入的哈希值:

my %PROCESSED = ();

if ($processing_done) {
  %PROCESSED{$dirname} = 1;
} else {
  %PROCESSED{$dirname} = 0;
}

您可以通过读取散列中的键值来检查每个目录是否已被处理:

if (%PROCESSED{$dirname} == 0) {
 ... do some processing
} else {
 ... this one is already done
}

答案 1 :(得分:0)

此解决方案查找尚未处理的所有目录,这些目录比最近处理的目标日期更新。您已经第一次手动记录它(在脚本运行之前)。该脚本将从该点开始更新。

该文件可以命名为my $last = 'dir_last.dat';我刚刚在命令行输入了一个文件,如:

C:\Old_Data\perlp>echo 11-07-14 > dir_last.bat

C:\Old_Data\perlp>type dir_last.bat
11-07-14

C:\Old_Data\perlp>

这假定最新目录为11-07-14。在运行脚本之前,您必须自己找到它。

#!/usr/bin/perl
use strict;
use warnings;
use File::Copy;

my $dir = shift or die "Provide path on command line. $!";

my $last = 'dir_last.dat';

open my $fh, "<", $last or die "Unable to open $last $!";
chomp(my $last_proc = <$fh>);
close $fh or die "Unable to close $last $!";

opendir my $dh, $dir or die "Opening failed for directory $dir $!";
my @dir = sort grep {-d && /^\d\d-\d\d-\d\d$/ && $_ gt $last_proc} readdir $dh;
closedir $dh or die "Unable to close $dir $!";
@dir or die "Found no date directories after last update: $last_proc";

my $fdir = '/some/example/path';

for my $date (@dir) {
    my $dday = "$dir/$date";
    my @gzfiles = glob("$dday/*tar.gz");

    foreach my $zf (@gzfiles) {  
        next if $zf =~ /BMP/ || $zf =~ /LG/ || $zf =~ /MAP/ || $zf =~ /STR/; 
        print "$zf\n";
        copy($zf, $fdir) or die "Unable to copy $zf to $fdir. $!";
    }
}

open  $fh, ">", $last or die "Unable to open $last $!";
print $fh "$dir[-1]\n"; # record the newest date-directory as processed
close $fh or die "Unable to close $last $!";

请注意,我不像第一个脚本那样依赖cwd。那里真的不需要,这里不需要。 opendirglobcopy都可以处理点(cwd)目录和相对路径。

标题包含行use strict;use warnings;。它们的目的是提醒您代码中的错误(大多数perl脚本都应该使用它们,除非专家决定将它们排除在外 - 出于什么原因我不知道)。第一行告诉unix在哪里找到解释器(perl)。

答案 2 :(得分:0)

嗯,正如mugen kenichi所建议的那样,另一种方法是使用Storable。这种方式存储包含所有已处理目录的哈希。然后,当您运行程序时,它可以检查哈希以查看它们是否已被处理。

您需要一次性脚本来设置已处理目录的哈希值。

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

# This script to be run 1 time only. Sets up 'processed' directories hash.
# After this script is run, ready to run the daily script.

my $dir = '.'; # or what ever directory the date-directories are stored in

opendir my $dh, $dir or die "Opening failed for directory $dir $!";
my @dir = grep {-d && /^\d\d-\d\d-\d\d$/ && $_ le '11-04-21'} readdir $dh;
closedir $dh or die "Unable to close $dir $!";

my %processed = map {$_ => 1} @dir;

store \%processed, 'processed_dirs.dat';

然后,定期运行脚本以查找和处理日期目录。

#!/usr/bin/perl
use strict;
use warnings;
use File::Copy;
use Storable;

my $dir = shift or die "Provide path on command line. $!";

my $processed = retrieve('processed_dirs.dat'); # $processed is a hashref

opendir my $dh, $dir or die "Opening failed for directory $dir $!";
my @dir = grep {-d && /^\d\d-\d\d-\d\d$/ && !$processed->{$_} } readdir $dh;
closedir $dh or die "Unable to close $dir $!";
@dir or die "Found no unprocessed date directories";

my $fdir = '/some/example/path';

for my $date (@dir) {
    my $dday = "$dir/$date";
    my @gzfiles = glob("$dday/*tar.gz");

    foreach my $zf (@gzfiles) {  
        next if $zf =~ /BMP/ || $zf =~ /LG/ || $zf =~ /MAP/ || $zf =~ /STR/; 
        print "$zf\n";
        copy($zf, $fdir) or die "Unable to copy $zf to $fdir. $!";
    }
    $processed->{ $date } = 1;
}

store $processed, 'processed_dirs.dat';
相关问题