Hoe verwijder ik recursief een map en zijn volledige inhoud (bestanden + submappen) in PHP?

Hoe verwijder ik een directory en de volledige inhoud (bestanden en subdirectories) in PHP?


Antwoord 1, autoriteit 100%

Het door de gebruiker bijgedragen gedeelte in de handleiding van rmdirbevat een degelijke implementatie:

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); 
   } 
 }

Antwoord 2, autoriteit 56%

Voortbouwend op De opmerking van de Pixel-ontwikkelaar, een fragment dat de SPL gebruikt, kan er als volgt uitzien:

$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);

Opmerking: het doet geengeestelijke controle en maakt gebruik van de SKIP_DOTS-vlag die is geïntroduceerd met de FilesystemIterator in PHP 5.3.0. Natuurlijk kan de $todoeen if/elsezijn. Het belangrijke punt is dat CHILD_FIRSTwordt gebruikt om eerst de onderliggende (bestanden) te herhalen vóór hun bovenliggende (mappen).


Antwoord 3, autoriteit 8%

Verwijdert alle bestanden en mappen in het pad.

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);
}

Antwoord 4, autoriteit 6%

Voor *nix kun je een shell_execgebruiken voor rm -Rof DEL /S folder_namevoor Windows.


Antwoord 5, autoriteit 2%

Er is een andere thread met meer voorbeelden hier:
Een recursieve verwijdermapfunctie voor PHP?

Als je Yii gebruikt, kun je dit aan het framework overlaten:

CFileHelper::removeDirectory($my_directory);

Antwoord 6, autoriteit 2%

<?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;
}

Antwoord 7

DirectoryIterator en recursie correct gebruiken:

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);
}

Antwoord 8

Het lijkt erop dat alle andere antwoorden aannemen dat het pad dat aan de functie wordt gegeven altijd een directory is. Deze variant werkt om zowel mappen als afzonderlijke bestanden te verwijderen:

/**
 * Recursively delete a file or directory.  Use with care!
 *
 * @param string $path
 */
function recursiveRemove(string $path) {
    if (is_dir($path)) {
        foreach (scandir($path) as $entry) {
            if (!in_array($entry, ['.', '..'], true)) {
                recursiveRemove($path . DIRECTORY_SEPARATOR . $entry);
            }
        }
        rmdir($path);
    } else {
        unlink($path);
    }
}

EDIT: als je kieskeurig bent (en je zou ook kieskeurig moeten zijn), wil je misschien code toevoegen om te controleren op scandir(), rmdir()en unlink()retourneert een fout en gooi een uitzondering als dat zo is.


Antwoord 9

‘eenvoudige’ code die werkt en kan worden gelezen door een tienjarige:

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);
    }
}

Houd er rekening mee dat alles wat ik deed was uitbreiden/vereenvoudigen en repareren (werkte niet voor niet-lege dir) de oplossing hier:
Hoe verwijder ik in PHP recursief alle mappen die niet leeg zijn?


Antwoord 10

Verbeterde oplossing van @Artefacto – gecorrigeerde typefouten en vereenvoudigde code, werkend voor beide – leeg && niet-lege mappen .

 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); 
    } 
  }

Antwoord 11

De 100% werkende oplossing

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);
    }
  }

Antwoord 12

Zoiets?

function delete_folder($folder) {
    $glob = glob($folder);
    foreach ($glob as $g) {
        if (!is_dir($g)) {
            unlink($g);
        } else {
            delete_folder("$g/*");
            rmdir($g);
        }
    }
}

Antwoord 13

Voorbeeld met de functie glob(). Het zal alle bestanden en mappen recursief verwijderen, inclusief bestanden die beginnen met een punt.

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 );
    }
};

Antwoord 14

unlinkr-functie verwijdert recursief alle mappen en bestanden in het opgegeven pad door ervoor te zorgen dat het script zelf niet wordt verwijderd.

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); 
        }
    }
}

als u alle bestanden en mappen waarin u dit script plaatst wilt verwijderen, noem het dan als volgt

//get current working directory
$dir = getcwd();
unlinkr($dir);

als je alleen php-bestanden wilt verwijderen, noem het dan als volgt

unlinkr($dir, "*.php");

u kunt ook elk ander pad gebruiken om de bestanden te verwijderen

unlinkr("/home/user/temp");

Hiermee worden alle bestanden in de map home/user/temp verwijderd.


Antwoord 15

Ik gebruik deze code …

function rmDirectory($dir) {
        foreach(glob($dir . '/*') as $file) {
            if(is_dir($file))
                rrmdir($file);
            else
                unlink($file);
        }
        rmdir($dir);
    }

of deze…

<?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); 
  } 
?>

Antwoord 16

Zodra u klaar bent met het uitvoeren van tests, verwijdert u gewoon #uit de #unlinken #rmdirin de klas .

<?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);
?>

Antwoord 17

<?php
/**
 * code by Nk ([email protected])
 */
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);
    }
}
?>

cleanup.php :

<?php
/* include.. */
filesystem::rrmdir('/var/log');
filesystem::rrmdir('./cache');
?>

Antwoord 18

Ik heb deze code zojuist gemaakt uit enkele StackOverflow-discussies. Ik heb nog niet getest in de Linux-omgeving. Het is gemaakt om een ​​bestand of een map volledig te verwijderen:

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'));

Antwoord 19

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 );
}

Antwoord 20

Gewijzigde variant van @XzaR-oplossing. Het verwijdert lege mappen wanneer alle bestanden eruit worden verwijderd en het genereert uitzonderingen in plaats van false te retourneren bij fouten.

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'");
        }
    }
}

Antwoord 21

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);
     }
}

Other episodes