Как удалить файлы из каталога по дате создания в php?
У меня есть папка кеша, в которой хранятся файлы HTML. Они перезаписываются, когда это необходимо, но в большинстве случаев там также кэшируются редко используемые страницы, которые в конечном итоге просто занимают место (через 5 недель диск был заполнен более чем 2,7 миллионами файлов кеша).
Как лучше всего пройти через каталог, содержащий несколько сотен тысяч файлов, и удалить файлы старше одного дня?
8 ответов
Я думаю, вы могли бы сделать это, перебирая каталог с помощью readdir и удаляя на основе метки времени:
if((time() — $filelastmodified) > 24*3600) выберет файлы старше 24 часов (24 часа умноженные на 3600 секунд в час). Если вам нужны дни, он должен читать, например, 7 * 24 * 3600 для файлов старше недели.
Также обратите внимание, что filemtime возвращает время последней модификации файла вместо даты создания.
if((time()-$filelastmodified) > 24*3600 && is_file($file))
Чтобы избежать ошибок для каталогов . и .. .
Следующая функция выводит список файлов по дате их создания:
private function listdir_by_date( $dir ) < $h = opendir( $dir ); $_list = array(); while( $file = readdir( $h ) )< if( $file != '.' and $file != '..' )< $ctime = filectime( $dir . $file ); $_list[ $file ] = $ctime; >> closedir( $h ); krsort( $_list ); return $_list; >
$_list = listdir_by_date($dir);
Теперь вы можете прокручивать список, чтобы увидеть их даты и соответственно удалить:
$now = time(); $days = 1; foreach( $_list as $file => $exp ) < if( $exp < $now-60*60*24*$days )< unlink( $dir . $file ); >>
// setup timezone and get timestamp for yesterday date_default_timezone_set('Europe/Berlin'); // change to yours $yesterday = strtotime('-1 day', time()); // setup path to cache dir and initialize iterator $path = realpath('/path/to/files'); // change to yours $objects = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($path)); // iterate over files in directory and delete them foreach($objects as $name => $object)< if ($object->isFile() && ($object->getCTime() < $yesterday)) < // unlink($object); echo PHP_EOL, 'deleted ' . $object; >>
/* Detele Cache Files Here */ $dir = "cache/"; /** define the directory **/ /*** cycle through all files in the directory ***/ foreach (glob($dir."*") as $file) < //foreach (glob($dir.'*.*') as $file)< /*** if file is 24 hours (86400 seconds) old then delete it ***/ if (filemtime($file) < time() - 3600) < // 1 hour unlink($file); >>
Я использую это, надеюсь, это поможет.
Просто чтобы отметить сравнение времени Гордона (см. выше: https://stackoverflow.com/a/2205833/1875965) только правильный вариант при сравнении с «днями», а не с «24 часами», поскольку не все дни имеют 24 часа (летнее / зимнее время и т. д.).
// setup timezone and get timestamp for yesterday date_default_timezone_set('Europe/Berlin'); // change as appropriate $yesterday = strtotime('-1 day', time());
Это может не быть большой проблемой, но может привести к неожиданному поведению, когда вы работаете с неделями / месяцами и т.д. путаница.
Также проверьте часовой пояс для дат файлов, так как иногда значение по умолчанию для PHP отличается от системного часового пояса.
$directory = $_SERVER['DOCUMENT_ROOT'].'/pathfromRoot/'; $files = array_slice(scandir($directory), 2); foreach($files as $file) < // $extension = substr($file, -3, 3); // if ($extension == 'jpg') // in case you only want specific files deleted // < $stat = stat($directory.$file); $filedate = date_create(date("Y-m-d", $stat['ctime'])); $today = date_create(date("Y-m-d")); $days = date_diff($filedate, $today, true); // dd($days); if ($days->days > 180) < unlink($directory.$file); >// > >
Изменив решение @pawel, я создал функцию ниже. Сначала я забыл добавить «путь» к имени файла, на это у меня ушло полчаса.
public function deleteOldFiles ($hours=24) < $path='cache'.DS; if ( $handle = opendir( $path ) ) < while (false !== ($file = readdir($handle))) < $filelastmodified = filemtime($path.$file); if((time()-$filelastmodified) >24*3600 && is_file($path.$file)) < unlink($path.$file); >> closedir($handle); > >
Как удалить файлы из каталога на основе даты создания в php?
У меня есть папка с кешем, в которой хранятся файлы html. Они перезаписываются, когда это необходимо, но в то же время в них кэшируются также редко используемые страницы, которые в конечном итоге используют пространство (через 5 недель диск был заполнен более 2,7 миллионами кеш-файлов).
Каков наилучший способ петли через каталог, содержащий несколько сотен тысяч файлов, и удалять файлы старше 1 дня?
Я думаю, вы могли бы это сделать, перейдя через каталог с readdir и удалив на основе метки времени:
Значение if((time() — $filelastmodified) > 24*3600) будет выбирать файлы старше 24 часов (24 часа раз 3600 секунд в час). Если вам нужны дни, он должен читать, например, 7 * 24 * 3600 для файлов старше недели.
Также обратите внимание, что filemtime возвращает время последней модификации файла, а не дату создания.
if((time()-$filelastmodified) > 24*3600 && is_file($file))
чтобы избежать ошибок для . и .. каталоги.
Следующая функция перечисляет файл в зависимости от даты создания:
private function listdir_by_date( $dir ) < $h = opendir( $dir ); $_list = array(); while( $file = readdir( $h ) )< if( $file != '.' and $file != '..' )< $ctime = filectime( $dir . $file ); $_list[ $file ] = $ctime; >> closedir( $h ); krsort( $_list ); return $_list; >
$_list = listdir_by_date($dir);
Теперь вы можете прокручивать список, чтобы увидеть их даты и удалить соответственно:
$now = time(); $days = 1; foreach( $_list as $file => $exp ) < if( $exp < $now-60*60*24*$days )< unlink( $dir . $file ); >>
// setup timezone and get timestamp for yesterday date_default_timezone_set('Europe/Berlin'); // change to yours $yesterday = strtotime('-1 day', time()); // setup path to cache dir and initialize iterator $path = realpath('/path/to/files'); // change to yours $objects = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($path)); // iterate over files in directory and delete them foreach($objects as $name => $object)< if ($object->isFile() && ($object->getCTime() < $yesterday)) < // unlink($object); echo PHP_EOL, 'deleted ' . $object; >>
Время создания доступно только в Windows.
/* Detele Cache Files Here */ $dir = "cache/"; /** define the directory **/ /*** cycle through all files in the directory ***/ foreach (glob($dir."*") as $file) < //foreach (glob($dir.'*.*') as $file)< /*** if file is 24 hours (86400 seconds) old then delete it ***/ if (filemtime($file) < time() - 3600) < // 1 hour unlink($file); >>
Я использую это, надеюсь, что это поможет.
просто отметить сравнение времени Гордона (см. выше: https://stackoverflow.com/a/2205833/1875965 ) является единственным правильным при сравнении с «днями», а не «24 часа», поскольку не все дни имеют 24 часа ( летнее время / зима и т. д.).
// setup timezone and get timestamp for yesterday date_default_timezone_set('Europe/Berlin'); // change as appropriate $yesterday = strtotime('-1 day', time());
Это может не быть большой проблемой, но может привести к неожиданному поведению, когда вы работаете с неделями / месяцами и т. Д. Я счел, что лучше всего использовать вышеупомянутый метод, поскольку он будет делать любой процесс, связанный с датами / временем, согласованным и избегать спутанность сознания.
Также проверьте, что такое часовой пояс для дат файла, поскольку иногда по умолчанию для PHP отличается от системного часового пояса.
С наилучшими пожеланиями, Сандра.
Изменив решение @ pawel, я создал функцию ниже. Сначала я забыл добавить «путь» к имени файла, который забирает мой полчаса, чтобы узнать.
public function deleteOldFiles ($hours=24) < $path='cache'.DS; if ( $handle = opendir( $path ) ) < while (false !== ($file = readdir($handle))) < $filelastmodified = filemtime($path.$file); if((time()-$filelastmodified) >24*3600 && is_file($path.$file)) < unlink($path.$file); >> closedir($handle); > >
Правильный способ удаления всех файлов старше 2 дней в PHP
Я просто хочу убедиться, что код правильный или нет. Благодарю.
Вы должны добавить is_file() , потому что PHP обычно перечисляет . и .. , а также подкаталоги, которые могут находиться в каталоге, который вы проверяете.
Кроме того, как следует из этого ответа , вы должны заменить предварительно рассчитанные секунды более выразительной нотацией.
В качестве альтернативы вы также можете использовать DirectoryIterator , как показано в этом ответе . В этом простом случае это не дает никаких преимуществ, но это будет ООП.
Самый простой способ – использовать DirectoryIterator :
Еще один более простой и более современный способ использования FilesystemIterator .
В качестве примера я использую каталог журналов.
$fileSystemIterator = new FilesystemIterator('logs'); $now = time(); foreach ($fileSystemIterator as $file) < if ($now - $file->getCTime() >= 60 * 60 * 24 * 2) // 2 days unlink('logs/'.$file->getFilename()); >
Главное преимущество: DirectoryIterator возвращает виртуальные каталоги «.» и «..» в цикле. Но FilesystemIterator игнорирует их.
Похоже на меня. Я просто предлагаю вам заменить 172800 на 2*24*60*60 для ясности.
Имейте в виду, что у вас возникнут проблемы, если в каталоге имеется очень большое количество файлов.
Если вы считаете, что это может повлиять на вас, подумайте об использовании подхода более низкого уровня, такого как opendir .
Вот пример того, как это сделать рекурсивно.
function remove_files_from_dir_older_than_x_seconds($dir,$seconds = 3600) < $files = glob(rtrim($dir, '/')."/*"); $now = time(); foreach ($files as $file) < if (is_file($file)) < if ($now - filemtime($file) >= $seconds) < echo "removed $file
".PHP_EOL; unlink($file); > > else < remove_files_from_dir_older_than_x_seconds($file,$seconds); >> > remove_files_from_dir_older_than_x_seconds(dirname(__file__).'/cache/', (60 * 60 * 24 * 1) ); // 1 day
/* Delete Cache Files Here */ $dir = "cache/"; /** define the directory **/ /*** cycle through all files in the directory ***/ foreach (glob($dir."*") as $file) < //foreach (glob($dir.'*.*') as $file)< /*** if file is 24 hours (86400 seconds) old then delete it ***/ if (filemtime($file) < time() - 172800) < // 2 days unlink($file); >>
/** It deletes old files. * @param string $dir Directory * @param int $secs Files older than $secs seconds * @param string $pattern Files matching $pattern */ function delete_oldfiles($dir,$secs,$pattern = "/*") < $now = time(); foreach(glob("$dir$pattern") as $f) < if (is_file($f) && ($now - filemtime($f) >$secs)) unlink($f); > >
Всякий блог
На своих сайтах я использую защиту от копирования контента на основе сессий и в результате на сервере скапливается большое количество каталогов с файлами с номерами сессий. Естественно их приходиться удалять в ручную. Чтобы избавиться от этой рутинной работы я решил автоматизировать процесс с помощью PHP скрипта.
Следующая функция занимается удалением файлов и всех каталогов в указанной директории.
function removeDirectory($dir)
if ($objs = glob($dir.»/*»))
foreach($objs as $obj)
is_dir($obj) ? removeDirectory($obj) : unlink($obj);
>
>
rmdir($dir);
>
?>
Функция нужна для того чтобы удалять как папки так и вложенные файлы, так как rmdir умеет удалять только пустые каталоги.
Далее нам необходимо определить все каталоги которые содержаться в указанной директории и после проверки на текущую и каталог уровня выше текущего («.» и «..»), что бы ненароком не затереть и весь свой сайт выполняем функцию которая описана выше.
if ($handle = opendir(‘../temp/’)) while (false !== ($entry = readdir($handle))) if ($entry != «.» && $entry != «..») $time_sec=time();
$time_file=filemtime(«../temp/$entry»);
$time=($time_sec-$time_file)/60;
if($time > 30)
removeDirectory(«../temp/$entry»);
>
>
>
closedir($handle);
>
?>
В текущем скрипте идет проверка на удаление каталогов которые старше 30 минут если нужно выбрать другое время то можно изменить условие if($time > 30)
Далее остается только добавить задание в cron. Но в случае с cron’ ом в скрипте необходимо указывать полные пути к папке так как задание запуститься, но файлы удалены не будут.