Как я могу получить последний измененный каталог в Perl? - PullRequest
1 голос
/ 22 октября 2009

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 ]

3 голосов
/ 22 октября 2009

Что ты делаешь? Звучит очень странно и чревато опасностью. Я, конечно, не хотел бы позволить сценарию CGI создавать новые каталоги. Возможно, будет лучшее решение для того, чего вы пытаетесь достичь.

Сколько каталогов вы ожидаете иметь? Чем больше записей у вас есть в любом каталоге, тем медленнее будут дела. Вы должны разработать схему, в которой вы можете хешировать вещи в структуру каталогов, которая распределяет файлы так, чтобы ни один каталог не содержал столько элементов. Скажем, если у вас есть имя «0123456789», вы создаете структуру каталогов, например:

 0/01/0123456789

Вы можете иметь столько уровней каталогов, сколько захотите. Смотрите структуру каталогов CPAN, например. Моего автора зовут BDFOY, поэтому мой каталог авторов - author / id / B / BD / BDFOY. Таким образом, не будет ни одного каталога с большим количеством записей (если ваш идентификатор автора не 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 голос
/ 22 октября 2009

Лучший способ открыть каталог, вернуть имя последнего 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;
    

Теперь проблема заключается в том, что между определением $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

Однако я должен отметить, что мне не очень понравился этот модуль за те несколько минут, которые я провел с ним, особенно одержимость автора модуля вызовом методов и функций в контексте списка. Я не думаю, что буду использовать его снова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...