Как удалить большое количество файлов рекурсивно (Скрипт на Perl)

Проблема и постановка задачи
Когда в linux в одном каталоге скапливается много файлов (более миллиона), то удалить их является нетривиальной задачей.
У меня случай несколько более сложный – в почтовом сервере в каждом почтовом ящике (каталоге на диске) пользователя миллионы файлов (писем) – задача удалить все файлы старше двух недель рекурсивно во всех ящиках.
Согласно вышеприведенному исследованию для решения задачи удаления большого количества файлов вполне годится Perl. По этому мной и был написан скрипт для рекурсивного удаления файлов с проверкой условия по каждому файлу.
Решение – Скрипт удаления файлов.
Использование:
recurse_rm.pl [-y] [<dirname>]
Ключ -y означает – не задвать вопроса при начале удаления файлов
Текст скрипта:
!!!!! для реального удаления раскомментировать строку 107 (unlink $filename;) !!!!!
#! /usr/bin/perl
#
# Скрипт удалят рекурсивно все файлы, у которых mtime сташе значения TIME_TO_KEEP
# если установлена переменная $delete_dirs то дополнительно удаляются пустые каталоги
#
# в самом низу скрипта есть процедура exclude_test в которую нужно добавить правила
# по которым будут пропускаться файлы
#
# !!!!! для реального удаления раскомментировать строку 108 (unlink $filename;) !!!!!
#
# $TIME_TO_KEEP в секундах!
# 1 min = 60 sec
# 1 hour = 3600 sec
# 24 hours= 86400 sec
# 7 days = 604800 sec
# 14 days = 1209600 sec
# 30 days = 2592000 sec
#
# ================== start of config constants =================
#
$debug = 1; # debug can be 0, 1, 2
$TIME_TO_KEEP=1209600; # время (в секундах) в течении которого хранить файлы, все что старше - удалить
#$TIME_TO_KEEP = 60;
#$DIR_NAME='/var/spool/mail/rusdc-archive'; # Каталог верхнего уровня с которого начать удаление
$DIR_NAME='/root/bin/test';
$delete_dirs = 0; # set to 1 if you want delete epty dirs too
#
# ================== end of config constants =================
#
$time_now=time;
$dirs_found=0;
$dirs_deleted=0;
$files_foud=0;
$files_deleted=0;
# command line parsing
print_usage() if (@ARGV == 0);
if (@ARGV == 1) {
$DIR_NAME=@ARGV[0];
print "Are you shure to recursive del files in $DIR_NAME? [y/n]";
$desigion=<stdin>; chomp $desigion;
exit if ($desigion ne "y");
}
if (@ARGV > 1) {
$DIR_NAME=@ARGV[1];
print_usage() if (@ARGV[0] ne "-y");
}
enter_dir ($DIR_NAME);
print " Dirs Found: $dirs_found \n Dirs Deleted: $dirs_deleted \n Files Found: $files_foud \n Files Deleted: $files_deleted\n";
exit;
# ================ enter_dir ===================
sub enter_dir {
local $dir_name=$_[0];
local $filename;
local *DIR;
$dirs_found++;
print "enter_dir $dir_name\n" if ($debug == 2);
opendir DIR, "$dir_name" || die;
while ($filename = readdir (DIR)) {
next if ($filename =~ m/^\./); # дальше, если имя начинается с точки
next if (exclude_test($filename) == 1 );
if (-d ($dir_name."/".$filename)){ # если это каталог, то входим в него = рекурсия
enter_dir ($dir_name."/".$filename);
next;
}
if (-f ($dir_name."/".$filename)){ # если это файл, то вызываем процедуру обработки файлов
examine_file (($dir_name."/".$filename));
next;
}
}
print "we close Dir $dir_name\n" if ($debug == 2);
closedir (DIR);
if ($delete_dirs > 0) {$dirs_deleted++ if (rmdir ($dir_name));}
}
# ================ examine_file ===================
sub examine_file {
local $filename=$_[0];
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat("$filename");
print "\t\t $filename == $mtime \n" if ($debug == 2);
print " Files Found: $files_foud \t Files Deleted: $files_deleted\n" if ($debug == 1);
$files_foud++;
if ($mtime < ($time_now - $TIME_TO_KEEP)){
print ("delete:\t".$dir."/".$filename."\n") if ($debug == 2);
$files_deleted++;
# unlink $filename; # !!!!! для реального удаления раскомментировать эту строку !!!!!
}
}
# ================ print_usage ===================
sub print_usage{
print " Usage: \t\t recurse_rm <dir>\n Or non-interactive: \t recurse_rm -y <dir>\n";
exit;
}
# ================ exclude_test ===================
# add here tests to exclude files you want
sub exclude_test {
local $filename=$_[0];
local $exclude=0;
$exclude=1 if ($filename =~ m/.*dovecot.*/);
if ($debug == 1) {print "File $filename excluded\n" if ($exclude ==1)}
return $exclude;
}

















