Как удалить устаревшие файлы и пустые каталоги для сборки мусораPhp

Кемеровские программисты php общаются здесь
Ответить
Anonymous
 Как удалить устаревшие файлы и пустые каталоги для сборки мусора

Сообщение Anonymous »

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

Код: Выделить всё

/path/to/cache
-> 7a68fba56
----> some_file.jpg
----> another_file.png
----> some_stuff.svg
-> b12a43293
----> some_picture.webp
----> selfie.avif
----> afile.png
----> profit.jpg
----> A-team-crew.jpg
-> 0fe2ba852
----> ...

Вот код:

Код: Выделить всё

class myGarbageCollector
{
protected $timeout = 1209600; // about 2 weeks: 60x60x24x14

public function __construct(array $directories)
{
foreach ($directories as $directory) {
$this->deleteStaleFiles($directory);
}
}

private function deleteStaleFiles($path)
{
$now  = time();
$dirs = new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS);
$iterator = new \RecursiveIteratorIterator($dirs, \RecursiveIteratorIterator::SELF_FIRST);

foreach ($iterator as $file) {
$filepath = $file->getRealPath();

// Delete file if:
// * It's an image
// * It's a dead link
// * It's last accessed more than $timeout seconds ago
if ($file->isFile()
&& strpos(mime_content_type($filepath), 'image/') === 0
&& (
($file->isLink() && !$file->isReadable()) || ($now - $file->getATime()) > $this->timeout)
) {
unlink($filepath);
}

// Remove empty directories too.
if ($file->isDir()) {
// Need to somehow count the files in this subdir and
// rmdir($filepath) if there are zero files inside
}
}
}
}

Думаю, у меня не получается использовать рекурсивный итератор. Он проходит в каталог, чтобы проверить файлы и удалить их, но я не вижу аккуратного способа доступа к «текущему» каталогу итератора для вызова getChildren() в нем (или что-то еще), поскольку $file является экземпляром SPLFileInfo, который предоставляет ограниченную информацию о текущем элементе.
Я ценю, что при любой данной очистке он может удалить все файлы в подкаталоге, и к тому времени это «прошел мимо» каталога, поэтому не удалит его. Это нормально, потому что при следующей очистке (при условии, что в этот подкаталог не было добавлено больше файлов) он удалит пустой каталог. Я не возражаю против этого (хотя, если удаление подкаталога можно выполнить за один проход, это даже лучше).
Может быть, я мог бы создать новый экземпляр DirectoryIterator(), используя текущий путь? Но это, конечно, сводит на нет смысл рекурсивного итератора?
Могу ли я рассматривать это как две отдельные вещи и использовать обычный DirectoryIterator для обхода подкаталогов непосредственно под кешем, а затем для каждого из них создавать новый DirectoryIterator для проверки файлов внутри него?
Я не женат на итераторах, поэтому, если что-то вроде scandir() или glob() будет более эффективным, тогда это круто. В кеше могут быть тысячи файлов, поэтому я ищу наиболее эффективное решение.

Подробнее здесь: https://stackoverflow.com/questions/798 ... collection
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Php»