Làm cách nào để xóa một thư mục và toàn bộ nội dung của nó (tệp và thư mục con) trong PHP?
Làm cách nào để xóa một thư mục và toàn bộ nội dung của nó (tệp và thư mục con) trong PHP?
Câu trả lời:
Phần do người dùng đóng góp trong trang hướng dẫn rmdir
chứa một triển khai hợp lý:
function rrmdir($dir) {
if (is_dir($dir)) {
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (is_dir($dir. DIRECTORY_SEPARATOR .$object) && !is_link($dir."/".$object))
rrmdir($dir. DIRECTORY_SEPARATOR .$object);
else
unlink($dir. DIRECTORY_SEPARATOR .$object);
}
}
rmdir($dir);
}
}
is_dir
hai lần cho mỗi thư mục đệ quy. Nếu đối số là một liên kết tượng trưng, nó cũng đi theo nó thay vì xóa liên kết tượng trưng, có thể hoặc không thể là những gì bạn muốn. Trong mọi trường hợp, đó không phải là những gì rm -rf
.
Dựa trên nhận xét của Nhà phát triển Pixel , đoạn trích sử dụng SPL có thể trông như sau:
$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);
Lưu ý: Nó không kiểm tra sự tỉnh táo và làm cho việc sử dụng SKIP_DOTS cờ được giới thiệu với các FilesystemIterator trong PHP 5.3.0. Tất nhiên, $todo
có thể là một if
/ else
. Điểm quan trọng là CHILD_FIRST
được sử dụng để lặp lại trên các tệp con trước các tệp (thư mục) của chúng.
SKIP_DOTS
chỉ được giới thiệu trong PHP 5.3? Bạn đã thấy điều đó ở đâu?
getPathname()
phương pháp thay vì getRealPath()
?
rmdir($dir)
phần cuối của kịch bản.
rmdir()
và unlink()
, ví dụ như hủy bỏ với E_WARNING
và lợi nhuận true
hoặc false
chỉ thành công.
FilesystemIterator
là một trình lặp đệ quy.
Xóa tất cả các tệp và thư mục trong đường dẫn.
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);
}
rm -rf /
== recurseRmdir('/')
:)
is_dir("$dir/$file")
thànhis_dir("$dir/$file") && !is_link("$dir/$file")
Đối với * nix, bạn có thể sử dụng shell_exec
cho rm -R
hoặc DEL /S folder_name
cho Windows.
DEL /S folder_name
Windows
RMDIR /S /Q folder_name
là những gì làm việc cho tôi
exec('rm -rf ' . __DIR__ . '/output/*.log');
<?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;
}
Có một luồng khác với nhiều ví dụ ở đây: Hàm thư mục loại bỏ đệ quy cho PHP?
Nếu bạn đang sử dụng Yii thì bạn có thể để nó vào khung:
CFileHelper::removeDirectory($my_directory);
Mã 'đơn giản' hoạt động và có thể được đọc bởi một đứa trẻ mười tuổi:
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);
}
}
Xin lưu ý rằng tất cả những gì tôi đã làm là mở rộng / đơn giản hóa và sửa lỗi (không hoạt động đối với thư mục không trống) giải pháp ở đây: Trong PHP làm cách nào để tôi loại bỏ đệ quy tất cả các thư mục không trống?
Giải pháp nâng cao của @Artefacto - đã sửa lỗi chính tả và mã đơn giản hóa, hoạt động cho cả hai - thư mục trống && không trống.
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);
}
}
Giải pháp làm việc 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);
}
}
Một cái gì đó như thế này?
function delete_folder($folder) {
$glob = glob($folder);
foreach ($glob as $g) {
if (!is_dir($g)) {
unlink($g);
} else {
delete_folder("$g/*");
rmdir($g);
}
}
}
Ví dụ với hàm global () . Nó sẽ xóa tất cả các tệp và thư mục theo cách đệ quy, bao gồm các tệp bắt đầu bằng dấu chấm.
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 );
}
};
system('rm -fr folder')
Hàm unlinkr xóa đệ quy tất cả các thư mục và tệp trong đường dẫn đã cho bằng cách đảm bảo rằng nó không xóa chính tập lệnh.
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);
}
}
}
Nếu bạn muốn xóa tất cả các tệp và thư mục nơi bạn đặt tập lệnh này, hãy gọi nó như sau
//get current working directory
$dir = getcwd();
unlinkr($dir);
Nếu bạn chỉ muốn xóa các tập tin php thì hãy gọi nó như sau
unlinkr($dir, "*.php");
bạn cũng có thể sử dụng bất kỳ đường dẫn nào khác để xóa các tập tin
unlinkr("/home/user/temp");
Điều này sẽ xóa tất cả các tập tin trong thư mục home / user / temp.
Tôi sử dụng mã này ...
function rmDirectory($dir) {
foreach(glob($dir . '/*') as $file) {
if(is_dir($file))
rrmdir($file);
else
unlink($file);
}
rmdir($dir);
}
hoặc cái này ...
<?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);
}
?>
Khi bạn hoàn thành việc chạy thử, chỉ cần xóa # khỏi #unlink và #rmdir trong lớp.
<?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);
}
}
?>
dọn dẹp.php:
<?php
/* include.. */
filesystem::rrmdir('/var/log');
filesystem::rrmdir('./cache');
?>
Dường như tất cả các câu trả lời khác đều cho rằng đường dẫn được cung cấp cho hàm luôn là một thư mục. Biến thể này hoạt động để loại bỏ các thư mục cũng như các tệp đơn lẻ:
/**
* Recursively delete a file or directory. Use with care!
*
* @param string $path
*/
function recursiveRemove($path) {
if (is_dir($path)) {
foreach (scandir($path) as $entry) {
if (!in_array($entry, ['.', '..'])) {
recursiveRemove($path . DIRECTORY_SEPARATOR . $entry);
}
}
rmdir($path);
} else {
unlink($path);
}
}
Sử dụng DirectoryIterator và đệ quy chính xác:
function deleteFilesThenSelf($folder) {
foreach(new DirectoryIterator($folder) as $f) {
if($f->isDot()) continue; // skip . and ..
if ($f->isFile()) {
unlink($f->getPathname());
} else if($f->isDir()) {
deleteFilesThenSelf($f->getPathname());
}
}
rmdir($folder);
}
Tôi vừa tạo mã này, từ một số cuộc thảo luận về StackOverflow. Tôi chưa thử nghiệm trên môi trường Linux. Nó được thực hiện để xóa một tập tin hoặc một thư mục, hoàn toàn:
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 );
}
Biến thể sửa đổi của giải pháp @XzaR. Nó xóa các thư mục trống, khi tất cả các tệp bị xóa khỏi chúng và nó ném ra các ngoại lệ thay vì trả về lỗi sai.
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);
}
}
unlink
, rmdir
) các opendir
+ readdir
công việc nhanh hơn scandir
và RecursiveDirectoryIterator
nó cũng được sử dụng ít bộ nhớ hơn tất cả. Để xóa thư mục tôi phải closedir
đầu tiên, tôi đã bị mắc kẹt ở đây. Nhờ câu trả lời này.