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

0
323

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

Как удалить большое количество файлов рекурсивно (Скрипт на Perl)
Как удалить большое количество файлов рекурсивно (Скрипт на 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;
}

источник