使用Perl将最后修改的Dir从一个位置复制到另一个位置

时间:2013-06-08 23:14:40

标签: perl

对于perl来说相当新,所以这很可能不是我发帖的最佳代码。我得到了这个工作,但想知道是否有更好的方法。我没有能力下载模块。我将构建文件夹中的最后一个修改目录从一个服务器复制到另一个服务器。该参数允许我选择可供选择的构建目录。 感谢

#!C:\strawberry\perl
use warnings;
use strict;

use File::Copy::Recursive;

my $NewFolder = `(dir /o-d/ad/b \\\\myserver1.name.com\\builds\\$ARGV[0] | head -1)`;
chomp($NewFolder);

 $dir1 = "\\\\myserver1.name.com\\builds\\$ARGV[0]/$NewFolder";
 $dir2 = "\\\\myserver2.name.com\\builds\\$ARGV[0]/Backup/$NewFolder";


File::Copy::Recursive::dircopy $dir1, $dir2 or die "Copy failed: $!";

1 个答案:

答案 0 :(得分:3)

使用正斜杠。它只是让你的代码更容易阅读:

$dir1 = "\\\\myserver1.name.com\\builds\\$ARGV[0]/$NewFolder";

VS

$dir1 = "//myserver1.name.com/builds/$ARGV[0]/$NewFolder";

另外,不要在Perl可以执行的情况下进行系统调用。例如,Perl可以通过stat查看文件的最后修改日期。更好的是File::stat模块使stat命令更容易使用。

请勿在您的计划中使用@ARGV。而是将@ARGV中的变量读入您自己的变量中。它使您的程序更易于理解,并且您自己的变量范围有限,而@ARGV是全局的。

使用现代约定。变量名称应全部为小写,并使用下划线分隔单词。那是$new_folder$NewFolder。这是武断的吗?是的,但这是大多数Perl开发人员遵循的惯例。这意味着不要怀疑变量是$newFolder$NewFolder还是$newfolder,因为您知道这些规则是$new_folder

最后,use autodie;这会在文件操作失败时终止程序。这将perl从错误编程语言的检查函数转换为异常检查语言。这样,您不必担心是否必须检查IO操作失败。

这是一个完全未经测试的错误示例:

use strict;
use warnings;
use autodie;
use File::Copy::Recursive qw(dircopy); #Optional Module
use File::Stat;

use constants {
    ORIG_SERVER => '//myserver1.name.com/builds',
    TO_SERVER   => '//myserver2.name.com/builds',
};

my $from_directory = shift;

#
# Find newest directory
#
opendir my $dir_fh, ORIG_SERVER . "/$from_directory";
my $newest_directory;

while ( my $sub_directory = readdir $dir_fh ) {
    next if $sub_directory eq "." or $sub_directory eq "..";
    next unless -d $sub_directory;

    if ( not defined $newest_directory ) {
        $youngest_directory = $sub_directory;
        next;
    }

    my $youngest_directory_stat = stat ORIG_SERVER . "/$directory/$newest_directory";
    my $sub_directory_stat = stat ORIG_SERVER . "/$directory/$sub_directory";
    if ( $newest_directory_stat->mtime > $sub_directory_stat->mtime ) {
       $newest_directory = $sub_directory;
    }
}

dircopy ORIG_SERVER . "/$directory/$youngest_directory",
    TO_SERVER . "/$directory/$youngest_directory/backup";

我的程序比你的程序长很多,因为你的程序依赖于各种系统操作命令,比如dirhead,我认为这些命令不是标准的Windows操作系统命令。相反,我将该目录下的每个条目都读入我的循环中。任何不是目录的东西,我抛出(next if -d $sub_directory)并抛弃特殊目录...

之后,我使用stat找到最年轻的目录,对我来说意味着具有最新修改时间的目录。请注意,Unix不存储创建时间。但是,根据perlport ctime是Win32上的创建时间,因此您可能更愿意使用而不是mtime

如果我没有使用File::stat,而不是:

my $youngest_directory_stat = stat ORIG_SERVER . "/$directory/$newest_directory";
my $sub_directory_stat = stat ORIG_SERVER . "/$directory/$sub_directory";
if ( $newest_directory_stat->mtime > $sub_directory_stat->mtime ) {
   $newest_directory = $sub_directory;
}

我本可以这样做:

my $newest = ORIG_SERVER . "/$directory/$newest_directory";
my $sub_dir = ORIG_SERVER . "/$directory/$sub_directory";
if ( stat( $newest )[9] > stat( $sub_dir )[9] ) {
   $newest_directory = $sub_directory;
}

没有stat的{​​{1}}命令返回一个值数组,我可以简单地使用该数组的File::stat元素。但是,什么是9?虽然它可以为我节省几行代码,并且包含一个额外的Perl模块,但最好使用[9]

你注意到的一件事是常量不插入,这意味着我必须继续做这样的事情:

File::stat

但是,您可以使用Perlish黑魔法的这一位来在引号内插入常量:

my $youngest_directory_stat = stat ORIG_SERVER . "/$directory/$newest_directory";

希望有所帮助。