Как рекурсивно удалить каталог и все его содержимое (файлы + sub dirs) в PHP?
Как удалить каталог и все его содержимое (файлы и подпапки) в PHP?
19 ответов:
вы пробовали первую заметку на странице руководства
rmdir
?function rrmdir($dir) { if (is_dir($dir)) { $objects = scandir($dir); foreach ($objects as $object) { if ($object != "." && $object != "..") { if (is_dir($dir."/".$object)) rrmdir($dir."/".$object); else unlink($dir."/".$object); } } rmdir($dir); } }
дом на комментарий разработчика пикселей, фрагмент с использованием SPL может выглядеть так:
$files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST ); foreach ($files as $fileinfo) { $todo = ($fileinfo->isDir() ? 'rmdir' : 'unlink'); $todo($fileinfo->getRealPath()); } rmdir($dir);
Примечание: это нет проверка здравомыслия и использует флаг SKIP_DOTS, введенный с помощью FilesystemIterator в PHP 5.3.0. Конечно же,
$todo
может бытьif
/else
. Важным моментом является то, чтоCHILD_FIRST
используется для перебора дочерних элементов (файлов) перед их родительскими (папками).
удаляет все файлы и папки в пути.
function recurseRmdir($dir) { $files = array_diff(scandir($dir), array('.','..')); foreach ($files as $file) { (is_dir("$dir/$file")) ? recurseRmdir("$dir/$file") : unlink("$dir/$file"); } return rmdir($dir); }
есть еще один поток с большим количеством примеров здесь: рекурсивная функция удаления каталога для PHP?
Если вы используете Yii, то вы можете оставить его в рамках:
CFileHelper::removeDirectory($my_directory);
<?php use RecursiveDirectoryIterator; use RecursiveIteratorIterator; use SplFileInfo; # http://stackoverflow.com/a/3352564/283851 # https://gist.github.com/XzaR90/48c6b615be12fa765898 # Forked from https://gist.github.com/mindplay-dk/a4aad91f5a4f1283a5e2 /** * Recursively delete a directory and all of it's contents - e.g.the equivalent of `rm -r` on the command-line. * Consistent with `rmdir()` and `unlink()`, an E_WARNING level error will be generated on failure. * * @param string $source absolute path to directory or file to delete. * @param bool $removeOnlyChildren set to true will only remove content inside directory. * * @return bool true on success; false on failure */ function rrmdir($source, $removeOnlyChildren = false) { if(empty($source) || file_exists($source) === false) { return false; } if(is_file($source) || is_link($source)) { return unlink($source); } $files = new RecursiveIteratorIterator ( new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST ); //$fileinfo as SplFileInfo foreach($files as $fileinfo) { if($fileinfo->isDir()) { if(rrmdir($fileinfo->getRealPath()) === false) { return false; } } else { if(unlink($fileinfo->getRealPath()) === false) { return false; } } } if($removeOnlyChildren === false) { return rmdir($source); } return true; }
'простой' код, который работает и может быть прочитан десятилетним:
function deleteNonEmptyDir($dir) { if (is_dir($dir)) { $objects = scandir($dir); foreach ($objects as $object) { if ($object != "." && $object != "..") { if (filetype($dir . "/" . $object) == "dir") { deleteNonEmptyDir($dir . "/" . $object); } else { unlink($dir . "/" . $object); } } } reset($objects); rmdir($dir); } }
обратите внимание, что все, что я сделал, это расширить/упростить и исправить (не работает для непустого dir) решение здесь: в PHP как рекурсивно удалить все папки, которые не пусты?
что-то вроде этого?
function delete_folder($folder) { $glob = glob($folder); foreach ($glob as $g) { if (!is_dir($g)) { unlink($g); } else { delete_folder("$g/*"); rmdir($g); } } }
расширенное решение @Artefacto-исправленные опечатки и упрощенный код, работающие как для пустых, так и для непустых каталогов .
function recursive_rmdir($dir) { if( is_dir($dir) ) { $objects = array_diff( scandir($dir), array('..', '.') ); foreach ($objects as $object) { $objectPath = $dir."/".$object; if( is_dir($objectPath) ) recursive_rmdir($objectPath); else unlink($objectPath); } rmdir($dir); } }
функция unlinkr рекурсивно удаляет все папки и файлы в заданном пути, убедившись, что он не удаляет сам скрипт.
function unlinkr($dir, $pattern = "*") { // find all files and folders matching pattern $files = glob($dir . "/$pattern"); //interate thorugh the files and folders foreach($files as $file){ //if it is a directory then re-call unlinkr function to delete files inside this directory if (is_dir($file) and !in_array($file, array('..', '.'))) { echo "<p>opening directory $file </p>"; unlinkr($file, $pattern); //remove the directory itself echo "<p> deleting directory $file </p>"; rmdir($file); } else if(is_file($file) and ($file != __FILE__)) { // make sure you don't delete the current script echo "<p>deleting file $file </p>"; unlink($file); } } }
если вы хотите удалить все файлы и папки, где вы размещаете этот скрипт, то вызовите его следующим образом
//get current working directory $dir = getcwd(); unlinkr($dir);
если вы хотите просто удалить только php файлы, то вызовите его следующим образом
unlinkr($dir, "*.php");
вы можете использовать любой другой путь для удаления файлов, а также
unlinkr("/home/user/temp");
это приведет к удалению всех файлов в каталог home / user / temp.
Как только вы закончите выполнение тестов, просто удалить # С #unlink и #rmdir в классе .
<?php class RMRFiles { function __construct(){ } public function recScan( $mainDir, $allData = array() ) { // hide files $hidefiles = array( ".", "..") ; //start reading directory $dirContent = scandir( $mainDir ) ; //cycle through foreach ( $dirContent as $key => $content ) { $path = $mainDir . '/' . $content ; // if is readable / file if ( ! in_array( $content, $hidefiles ) ) { if ( is_file( $path ) && is_readable( $path ) ) { #delete files within directory #unlink($path); $allData['unlink'][] = $path ; } // if is readable / directory else if ( is_dir( $path ) && is_readable( $path ) ) { /*recursive*/ $allData = $this->recScan( $path, $allData ) ; #finally remove directory $allData['rmdir'][]=$path; #rmdir($path); } } } return $allData ; } } header("Content-Type: text/plain"); /* Get absolute path of the running script Ex : /home/user/public_html/ */ define('ABPATH', dirname(__file__) . '/'); /* The folder where we store cache files Ex: /home/user/public_html/var/cache */ define('STOREDIR','var/cache'); $rmrf = new RMRFiles(); #here we delete folder content files & directories print_r($rmrf->recScan(ABPATH.STOREDIR)); #finally delete scanned directory ? #rmdir(ABPATH.STOREDIR); ?>
<?php /** * code by Nk (nk.have.a@gmail.com) */ class filesystem { public static function remove($path) { return is_dir($path) ? rmdir($path) : unlink($path); } public static function normalizePath($path) { return $path.(is_dir($path) && !preg_match('@/$@', $path) ? '/' : ''); } public static function rscandir($dir, $sort = SCANDIR_SORT_ASCENDING) { $results = array(); if(!is_dir($dir)) return $results; $dir = self::normalizePath($dir); $objects = scandir($dir, $sort); foreach($objects as $object) if($object != '.' && $object != '..') { if(is_dir($dir.$object)) $results = array_merge($results, self::rscandir($dir.$object, $sort)); else array_push($results, $dir.$object); } array_push($results, $dir); return $results; } public static function rrmdir($dir) { $files = self::rscandir($dir); foreach($files as $file) self::remove($file); return !file_exists($dir); } } ?>
очистка.php:
<?php /* include.. */ filesystem::rrmdir('/var/log'); filesystem::rrmdir('./cache'); ?>
100% рабочий раствор
public static function rmdir_recursive($directory, $delete_parent = null) { $files = glob($directory . '/{,.}[!.,!..]*',GLOB_MARK|GLOB_BRACE); foreach ($files as $file) { if (is_dir($file)) { self::rmdir_recursive($file, 1); } else { unlink($file); } } if ($delete_parent) { rmdir($directory); } }
Я только что сделал этот код, из некоторых обсуждений StackOverflow. Я еще не тестировал среду Linux. Это сделано для того, чтобы удалить файл или каталог, полностью :
function splRm(SplFileInfo $i) { $path = $i->getRealPath(); if ($i->isDir()) { echo 'D - ' . $path . '<br />'; rmdir($path); } elseif($i->isFile()) { echo 'F - ' . $path . '<br />'; unlink($path); } } function splRrm(SplFileInfo $j) { $path = $j->getRealPath(); if ($j->isDir()) { $rdi = new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS); $rii = new RecursiveIteratorIterator($rdi, RecursiveIteratorIterator::CHILD_FIRST); foreach ($rii as $i) { splRm($i); } } splRm($j); } splRrm(new SplFileInfo(__DIR__.'/../dirOrFileName'));
function rmdir_recursive( $dirname ) { /** * FilesystemIterator and SKIP_DOTS */ if ( class_exists( 'FilesystemIterator' ) && defined( 'FilesystemIterator::SKIP_DOTS' ) ) { if ( !is_dir( $dirname ) ) { return false; } foreach( new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dirname, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::CHILD_FIRST ) as $path ) { $path->isDir() ? rmdir( $path->getPathname() ) : unlink( $path->getRealPath() ); } return rmdir( $dirname ); } /** * RecursiveDirectoryIterator and SKIP_DOTS */ if ( class_exists( 'RecursiveDirectoryIterator' ) && defined( 'RecursiveDirectoryIterator::SKIP_DOTS' ) ) { if ( !is_dir( $dirname ) ) { return false; } foreach( new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dirname, RecursiveDirectoryIterator::SKIP_DOTS ), RecursiveIteratorIterator::CHILD_FIRST ) as $path ) { $path->isDir() ? rmdir( $path->getPathname() ) : unlink( $path->getRealPath() ); } return rmdir( $dirname ); } /** * RecursiveIteratorIterator and RecursiveDirectoryIterator */ if ( class_exists( 'RecursiveIteratorIterator' ) && class_exists( 'RecursiveDirectoryIterator' ) ) { if ( !is_dir( $dirname ) ) { return false; } foreach( new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dirname ), RecursiveIteratorIterator::CHILD_FIRST ) as $path ) { if ( in_array( $path->getFilename(), array( '.', '..' ) ) ) { continue; } $path->isDir() ? rmdir( $path->getPathname() ) : unlink( $path->getRealPath() ); } return rmdir( $dirname ); } /** * Scandir Recursive */ if ( !is_dir( $dirname ) ) { return false; } $objects = scandir( $dirname ); foreach ( $objects as $object ) { if ( $object === '.' || $object === '..' ) { continue; } filetype( $dirname . DIRECTORY_SEPARATOR . $object ) === 'dir' ? rmdir_recursive( $dirname . DIRECTORY_SEPARATOR . $object ) : unlink( $dirname . DIRECTORY_SEPARATOR . $object ); } reset( $objects ); rmdir( $dirname ); return !is_dir( $dirname ); }
delete_all( 'folder' ); function delete_all( $item ) { if ( is_dir( $item ) ) { array_map( 'delete_all', array_diff( glob( "$item/{,.}*", GLOB_BRACE ), array( "$item/.", "$item/.." ) ) ); rmdir( $item ); } else { unlink( $item ); } };
модифицированный вариант решения @XzaR. Он удаляет пустые папки, когда все файлы удаляются из них, и он выдает исключения вместо возврата false при ошибках.
function recursivelyRemoveDirectory($source, $removeOnlyChildren = true) { if (empty($source) || file_exists($source) === false) { throw new Exception("File does not exist: '$source'"); } if (is_file($source) || is_link($source)) { if (false === unlink($source)) { throw new Exception("Cannot delete file '$source'"); } } $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST ); foreach ($files as $fileInfo) { /** @var SplFileInfo $fileInfo */ if ($fileInfo->isDir()) { if ($this->recursivelyRemoveDirectory($fileInfo->getRealPath()) === false) { throw new Exception("Failed to remove directory '{$fileInfo->getRealPath()}'"); } if (false === rmdir($fileInfo->getRealPath())) { throw new Exception("Failed to remove empty directory '{$fileInfo->getRealPath()}'"); } } else { if (unlink($fileInfo->getRealPath()) === false) { throw new Exception("Failed to remove file '{$fileInfo->getRealPath()}'"); } } } if ($removeOnlyChildren === false) { if (false === rmdir($source)) { throw new Exception("Cannot remove directory '$source'"); } } }
Я использую этот код ...
function rmDirectory($dir) { foreach(glob($dir . '/*') as $file) { if(is_dir($file)) rrmdir($file); else unlink($file); } rmdir($dir); }
или вот этот...
<?php public static function delTree($dir) { $files = array_diff(scandir($dir), array('.','..')); foreach ($files as $file) { (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file"); } return rmdir($dir); } ?>
function deltree_cat($folder) { if (is_dir($folder)) { $handle = opendir($folder); while ($subfile = readdir($handle)) { if ($subfile == '.' or $subfile == '..') continue; if (is_file($subfile)) unlink("{$folder}/{$subfile}"); else deltree_cat("{$folder}/{$subfile}"); } closedir($handle); rmdir ($folder); } else { unlink($folder); } }