2014-08-27 2 views
2

=================Perl: Самый быстрый способ найти файлы старше X минут, отсортированные по старейшему и новейшему?

1. Найдите файлы старше X количество минут

2. Процесс их от старых к новым

Код ниже работает нормально, однако каталог содержит 3 миллиона файлов. Поэтому мне нужно оптимизировать его, чтобы быстрее находить файлы. Мне не нужно беспокоиться о содержимом файла, просто имя.

########################### 
sub get_files_to_process{ 
########################### 
# Declare arrays 
my @xmlfiles; 
my @qulfiedfiles; 

# Declare a Dictionary 
my %filedisc; 

opendir(my $dh, $maindir) or die "opendir($maindir): $!"; 

# Read all the files 
while (my $de = readdir($dh)) { 
    # get the Full path of the file 
    my $f = $maindir . $de; 
    # If File is there and has .xml Extension 
    if (-f $f && $f=~ /\.xml/){ 
     # Put it in a XMLFILES Array 
     push (@xmlfiles, $f); } 
    } 
    closedir($dh); 


# For every file in directory 
for my $file (@xmlfiles) { 

    # Get stats about a file 
    my @stats = stat($file); 

    # If time stamp is older than minutes provided 
    if ($stats[9] <= ($now - (($minutesold * 60)))){ 

     # Put the File and Time stamp in the dictionary 
     $filedisc{$file} = $stats[9]; 
    } 
} 

# For every file in the dictionary sort based on the timestamp oldest files first 
for my $x (sort {$filedisc{$a} <=> $filedisc{$b} or $a cmp $b } keys %filedisc) { 

    # Put the qualified files (Based on the age) in a list 
     push(@qulfiedfiles, $x);} 

UPDATE: До сих пор это кажется перспективным, более тестирование должно быть сделано:

########################## 
sub get_files_count{ 
########################## 

    my $cmd= "find $maindir -maxdepth 1 -name '*.xml' -mmin +$minutesold -printf \"%T+\t%p\\n\"| sort"; 
    my @output = `$cmd`; 

    if (@output){ 
     foreach my $line (@output){ 
      chomp $line; 
      push (@files2process, (split '\t', $line)[ -1 ]); 
     } 
     } 
    } 
+2

Я не тестировал ваш код в каталоге с 3_000_000 записей. Прежде чем мы начнем говорить о способах оптимизации кода, почему бы вам не использовать 'Devel :: NYTProf', чтобы определить, где ваш код тратит больше времени? – DavidO

+0

Как вы обрабатываете файлы после того, как у вас есть список? – ThisSuitIsBlackNot

+0

@ThisSuitIsBlackNot, Как только у меня есть список файлов, я основываясь на имени файла, я перемещаю файл в соответствующие подкаталоги (и создаю sub-dir, если он еще не существует), этот скрипт будет работать из cron каждый От 5 до 10 минут, приложение Enterpise генерирует тонны xml-файлов, и это ухаживает за этими файлами. – Grene

ответ

2

Использование File :: Find

use File::Find 

$\ = "\n"; 

my @files; 

# find all files newer that 9 minutes 
File::Find::find({wanted => \&wanted}, '.'); 

# sort them and print them 
print for map { $_-[0] } sort { $b->[1] <=> $a->[1] } @files; 

exit; 

sub wanted { 
    ((-M) < (9/(24 * 60))) && -f && push @files, [ $_, (-M) ]; 
} 

Это рекурсивная - так будет идти через все подкаталоги (но я полагаю, что из вашего вопроса их нет).

Кроме того, вышесказанное является главным образом автоматически сгенерированным кодом из find2perl, который переводит большинство параметров поиска unix в perl-скрипт - круто и быстро.

Я не тестировал бит-М с помощью 9 минут - за последние 9 минут я ничего не спас.

+1

Вы сравнили время выполнения этого предложения с тем, что использует OP в настоящее время, или это просто интуиция, что он будет значительно быстрее? ... потому что мы не хотели бы слишком волноваться из-за незначительных улучшений или регрессий. – DavidO

1

Я бы решить эту проблему в два этапа:

1) создать Linux::Inotify2 процесс, что при каждом изменении на каталог будет обновляет некоторые cahce файл (например, убирающийся или такой)

например у вас будет фактический кеш всех файлов. Загрузка одного файла Storable быстрее, как статистика сбора для файлов 3Х при каждом запуске

2), когда нужно искать, загружать только Storable, поиск один большой хэш ...

+0

Спасибо за ваш вклад. Это очень умное решение, и я обязательно рассмотрю его. К сожалению, это приложение для предприятий, есть много других предостережений. – Grene

+0

@ Grene просто прокомментировал это снова с тем же комментарием. Так что, возможно, все еще борется с вопросом. Не могли бы вы быть более конкретными? Например. используемая ОС и т. д.? И вы сказали в комментарии _, и это будет ухаживать за этими файлами. Итак, когда вы когда-то переместили их в поддиры, как они посчитали, может быть снова 3_000_000 за короткий промежуток времени, так что вам нужна такая экстремальная статичность? Это звучит для меня как абсурд ... Пожалуйста, задайте реальный вопрос - не гипотетический - в противном случае вы не получите никаких соответствующих ответов ... – jm666

+0

Извините, я просто исправлял опечатку в своем комментарии. Поскольку я опубликовал обновление по этому вопросу, он работает в приемлемом временном диапазоне и намного быстрее, чем то, что у меня было до этого. Просто больше информации. Проблема реальна, сценарий должен запускаться каждые 30 минут, приложение генерирует около ~ 100k xml файлов за этот период времени, однако первоначальное отставание файлов действительно огромно и монтируется поверх NFS. Для обработки файлов в порядке их генерации требуется много времени. Скрипт является частью более крупного приложения, поэтому извините, я не представил достаточно подробностей. – Grene

0

Я знаю, что это старое вопрос. Я в основном отвечаю за него за «будущие поколения».

Большую часть своего времени весьма вероятно, провел в сортировки 3 миллиона записей файлов, поскольку операции сортировки являются нелинейными (т.е. сортировка становится все медленнее и медленнее, чем больше файлов вы имеете), а также потому, что большинство стат вызовы происходят в сравнении, которые в основном происходят из-за сортировки. (Также список файлов, вероятно, займет довольно много места в вашей памяти.)

Так что, если вы можете избежать сортировки, вы также автоматически избегаете большинства вызовов stat и сохраняете тонну времени. Поскольку ваша задача - просто «переместить файлы в соответствующие каталоги», я бы просто назвал метод обработки для каждого найденного вами файла, который соответствует вашим критериям, в тот момент, когда вы найдете его, в отличие от первого создания огромного списка, используйте связку циклов, чтобы отсортировать его, а затем пройти через огромный список и обработать его таким образом, чтобы не обязательно сортировать в первую очередь.

Пример из вашего собственного скрипта: «найти», в отличие от «ls», не создать список файлов в памяти - он выполняет команды для каждого файла в тот момент, когда он его находит. Вот почему он не взрывается с огромными каталогами, в отличие от «ls». Просто сделайте это, как найти. ^^