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

发布于 2024-08-08 19:35:34 字数 1093 浏览 2 评论 0原文

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

好的,这是我正在做的事情。但是,我可能不会在脚本的其余部分中使用 File::Util 来执行其他任何操作。

我的目录名称是从 10000000 开始的 8 位数字。 我将找到的最高数字与 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 调用更好?

Apache version 2.2.11 (Unix)
Architecture x86_64
Operating system Linux
Kernel version 2.6.18-164.el5

Ok, here is what I have working. However, I may not be using File::Util for anything else in the rest of the script.

My directory names are 8 digits starting at 10000000 .
I was comparing the highest found number with stat last created as a double check but, overkill I believe.

Another issue is that I did not know how to slap a regex in the list_dir command so only 8 digits eg m!^([0-9]{8})\z!x) could reside in that string. Reading the man, the example reads ....'--pattern=\.txt$') but, my futile attempt: '--pattern=m!^([0-9]{8})\z!x)') well, was just that.

So, would there be a "better" way to grab the latest folder/directory?

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";

And.. How would I ignore anything not matching my regex?

I was thinking an answer may reside in ls -d as well but, as a beginner here, I am new to system calls from a script (and if in fact that's what that would be? ;-) ).

More specifically:
Best way to open a directory, return the name of the latest 8 digit directory in that directory ignoring all else. Increase the 8 digit dir name by 1 and create the new directory.
Whichever is most efficient: stat or actual 8 digit file name. (directory names are going to be 8 digits either way.) Better to use File::Util or just built in Perl calls?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

看透却不说透 2024-08-15 19:35:34

你在干什么?听起来真的很奇怪而且充满危险。我当然不想让 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 更快地完成此任务。如果有大量目录,则您自己检查所有内容所需要做的工作应该会超过分叉的成本。

然而,我怀疑您真正需要的是某种数据库。

What are you doing? It sounds really weird and fraught with danger. I certainly wouldn't want to let a CGI script create new directories. There might be a better solution for what you are trying to achieve.

How many directories do you expect to have? The more entries you have in any directory, the slower things are going to get. You should work out a scheme where you can hash things into a directory structure that spreads out the files so no directory holds that many items. Say, it you have the name '0123456789', you create the directory structure like:

 0/01/0123456789

You can have as many directory levels as you like. See the directory structure of CPAN, for instance. My author name is BDFOY, so my author directory is authors/id/B/BD/BDFOY. That way there isn't any directory that has a large number of entries (unless your author id is ADAMK or RJBS).

You also have a potential contention issue to work out. Between the time you discover the latest and the time you try to make the next one, you might already create the directory.

As for the task at hand, I think I'd punt to system for this one if you are going to have a million directories. With something like:

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

I don't think you'll be able to get any faster than ls for this task. If there are a large number of directories, the cost of the fork should be outweighed by the work you have to do to go through everything yourself.

I suspect, however, that what you really need is some sort of database.

撞了怀 2024-08-15 19:35:34

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

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

  1. 如何只获取由八位数字组成的目录名称?

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

    use List::Util qw( max );
    我的 $latest = max @dirs;
    

现在的问题是,在确定 $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

但是,我必须指出,在我使用它的几分钟内,我不太喜欢这个模块,尤其是模块作者的痴迷于在列表上下文中调用方法和函数。我想我不会再使用它了。

Best way to open a directory, return the name of the latest 8 digit directory in that directory ignoring all else. Increase the 8 digit dir name by 1 and create the new directory. Whichever is most efficient: stat or actual 8 digit file name?

First, I should point out that having about 100,000,000 subdirectories in a directory is likely to be very inefficient.

  1. How do you get only the directory names that consist of eight digits?

    use File::Slurp;
    my @dirs = grep { -d and /\A[0-9]{8}\z/ } read_dir $top;
    
  2. How do you get the largest?

    use List::Util qw( max );
    my $latest = max @dirs;
    

Now, the problem is, between the determination of $latest and the attempt to create the directory, some other process can create the same directory. So, I would use $latest as the starting point and keep trying to create the next directory until I succeed or run out of numbers.

#/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;
}

If you try to do it the way I originally recommended, you will invoke mkdir way too many times.

As for how you use File::Util::list_dir to filter entries:

#/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

However, I must point out that I did not much like this module in the few minutes I spent with it, especially the module author's obsession with invoking methods and functions in list context. I do not think I will be using it again.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文