如何在Perl中获取最后更改的目录?

时间:2009-10-22 16:06:51

标签: perl directory

Apache 2.2.11版(Unix) 架构x86_64 操作系统Linux 内核版本2.6.18-164.el5

好的,这就是我的工作。但是,我可能没有在脚本的其余部分中使用File::Util来执行任何其他操作。

我的目录名是8位数,起始于10000000。 我将最高找到的数字与stat last created作为双重检查进行比较,但是我相信它有点过分了。

另一个问题是我不知道如何在list_dir命令中使用正则表达式,因此只有8位数字,例如m!^([0-9]{8})\z!x)可以驻留在该字符串中。读这个男人,这个例子是...... '--pattern=\.txt$'),但是,我的徒劳尝试:'--pattern=m!^([0-9]{8})\z!x)')嗯,就是这样。

那么,有没有“更好”的方法来获取最新的文件夹/目录?

use File::Util;
my($f) = File::Util->new();
my(@dirs) = $f->list_dir('/home/accountname/public_html/topdir','--no-fsdots');
my @last = (sort { $b <=> $a } @dirs); 
my $new = ($last[0]+1);
print "Content-type: text/html\n\n";
print "I will now create dir $new\n";

而且..我怎么会忽略任何与我的正则表达不匹配的东西?

我认为答案可能也存在于ls -d中,但作为初学者,我不熟悉来自脚本的系统调用(如果事实上那将是什么?;-))。

更具体地说: 打开目录的最佳方法,返回该目录中最新的8位数目录的名称,忽略其他所有目录。将8位数的目录名称增加1并创建新目录。 最有效的是:stat或实际的8位数文件名。 (目录名称无论哪种方式都是8位数。)最好使用File::Util还是只是内置Perl调用?

2 个答案:

答案 0 :(得分:3)

你正在做什么?这听起来很奇怪,充满了危险。我当然不希望让CGI脚本创建新目录。对于您想要实现的目标,可能有更好的解决方案。

您希望有多少个目录?您在任何目录中拥有的条目越多,获得的速度就越慢。你应该制定一个方案,你可以将一些东西散列到一个扩展文件的目录结构中,这样就没有目录可以容纳那么多项。比如,你有了名字'0123456789',你创建了如下目录结构:

 0/01/0123456789

您可以拥有任意数量的目录级别。例如,请参阅CPAN的目录结构。我的作者姓名是BDFOY,所以我的作者目录是authors / id / B / BD / BDFOY。这样就没有任何目录有大量条目(除非您的作者ID是ADAMK或RJBS)。

您还有一个潜在的争用问题需要解决。在您发现最新版本的时间和尝试创建下一个版本的时间之间,您可能已经创建了目录。

至于手头的任务,如果你要拥有一百万个目录,我想我会向system寻找。有类似的东西:

ls -t -d -1 [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -1

对于此任务,我认为你不会比ls更快。如果有大量的目录,那么你自己必须完成的所有工作都应该超过分支的成本。

但是,我怀疑你真正需要的是某种数据库。

答案 1 :(得分:1)

  

打开目录的最佳方式,返回该目录中最新8位数目录的名称,忽略其他所有目录。将8位数的目录名称增加1并创建新目录。哪个最有效:统计或实际的8位数文件名?

首先,我应该指出,在目录中拥有大约100,000,000个子目录可能效率很低。

  1. 如何只获得包含八位数的目录名?

    use File::Slurp;
    my @dirs = grep { -d and /\A[0-9]{8}\z/ } read_dir $top;
    
  2. 你如何获得最大的?

    use List::Util qw( max );
    my $latest = max @dirs;
    
  3. 现在,问题是,在确定$latest和创建目录的尝试之间,其他一些进程可以创建相同的目录。所以,我会使用$latest作为起点,并继续尝试创建下一个目录,直到我成功或用完数字。

    #/usr/bin/perl
    
    use strict;
    use warnings;
    
    use File::Slurp;
    use File::Spec::Functions qw( catfile );
    use List::Util qw( max );
    
    sub make_numbered_dir {
        my $max = 100_000_000;
        my $top = '/home/accountname/public_html/topdir';
        my $latest = max grep { /\A[0-9]{8}\z/ } read_dir $top;
    
        while ( ++$latest < $max ) {
            mkdir catfile($top, sprintf '%8.8d', $latest)
                and return 1;
        }
        return;
    }
    

    如果你按照我最初推荐的方式尝试,你会多次调用mkdir

    至于如何使用File::Util::list_dir过滤条目:

    #/usr/bin/perl
    
    use strict;
    use warnings;
    
    use File::Util;
    
    my $fu = File::Util->new;
    
    print "$_\n" for $fu->list_dir('.',
        '--no-fsdots',
        '--pattern=\A[0-9]{8}\z'
    );
    
    C:\Temp> ks
    10001010
    12345678
    

    但是,我必须指出,在我花费的几分钟内,我不太喜欢这个模块,特别是模块作者对在列表上下文中调用方法和函数的痴迷。我不认为我会再次使用它。