Как удалить каталог и все его содержимое (файлы и подкаталоги) в PHP?
Вы пробовали первую заметку на странице руководства 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); } }
Основываясь на комментарии разработчика Pixel , фрагмент с использованием 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, введенный с помощью FileystemIterator в PHP 5.3.0. Конечно, $todo
может быть if
/ else
. Важным моментом является то, что CHILD_FIRST
используется для итерации над CHILD_FIRST
(файлами) перед их родителями (папками).
Для * nix вы можете использовать shell_exec
для rm -R
или DEL /S folder_name
для Windows.
Удаляет все файлы и папки в пути.
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 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 - egthe 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; }
Существует еще один поток с большим количеством примеров: Рекурсивная функция удаления каталога для PHP?
Если вы используете Yii, вы можете оставить его в рамке:
CFileHelper::removeDirectory($my_directory);
Что-то вроде этого?
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); ?>
«простой» код, который работает и может быть прочитан десятилетним:
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); } }
Обратите внимание, что все, что я сделал, было расширение / упрощение и исправление (не работало для непустого каталога ): здесь: В PHP, как я рекурсивно удаляю все папки, которые не пусты?
Я сделал этот код из некоторых обсуждений в 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 ); }
Пример с функцией glob () . Он будет рекурсивно удалять все файлы и папки, включая файлы, начинающиеся с точки.
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 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); } }
Я использую этот код …
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); } ?>