PHP'de bir dizini ve tüm içeriğini (dosyalar + alt dizinler) yinelemeli olarak nasıl silebilirim?


Yanıtlar:


207

Kılavuz sayfasındaki kullanıcı katkıda bulunan bölüm rmdiriyi bir uygulama içeriyor:

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

1
@ Pixel Developer - Bunu gösteren bir cevap ekledim .
salathe

2
birisinin bana aynı soru için verdiği çözümü inceleyin: glob daha iyi çalışıyor gibi görünüyor: stackoverflow.com/questions/11267086/…
NoodleOfDeath

Bu, is_diryinelenen her dizin için iki kez çağırır . Bağımsız değişken bir symlink ise, istediğiniz gibi veya olmayabilir, symlink'i silmek yerine bunu izler. Her durumda, öyle değil rm -rf.
Vladimir Panteleev

116

Pixel Developer'ın yorumuna dayanarak , SPL'yi kullanan bir snippet şöyle görünebilir:

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

Not: It does hiçbir aklı denetimi ve PHP 5.3.0 yılında FilesystemIterator ile tanıtılan SKIP_DOTS bayrak kullanır. Tabii ki, $todobir if/ olabilir else. Önemli olan nokta, CHILD_FIRSTönce ebeveynlerden (klasörler) önce çocukları (dosyaları) tekrarlamak için kullanılır.


SKIP_DOTSsadece PHP 5.3'te kullanılmaya başlandı mı? Bunu nerede gördün?
Alix Axel

Teşekkür ederim. Ayrıca: getPathname()yerine yöntemi kullanmamalısınız getRealPath()?
Alix Axel

3
Bu çözüm iyi çalışıyor, ancak dizin hariç (boş olsun veya olmasın) her şeyi siler. rmdir($dir)Senaryo sonunda bir olmalıdır .
laurent

3
Burada, aynı işlev , kaydırılmamış, doc-bloke edilmiş rmdir()ve ile tutarlı hale getirilmiştir ve unlink()örneğin, örneğin iptal eder E_WARNINGve geri döner trueveya falsebaşarıyı gösterir.
mindplay.dk

2
@dbf hayır olmaz, FilesystemIteratorözyinelemeli yineleyici değildir.
Salathe

17

Yoldaki tüm dosya ve klasörleri siler.

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

1
rm -rf /== recurseRmdir('/'):)
Aaron Esau

5
Bunun sembolik güvenli olmadığını lütfen unutmayın! Ayrıca, is_dir olup olmadığını kontrol etmek için is_dir'den sonra bir sağlık kontrolüne ihtiyacınız vardır, aksi takdirde silinmiş olan harici bir klasöre simge bağlayabilirsiniz ve bu bir güvenlik deliği olarak kabul edilebilir. Yani değişmelidir is_dir("$dir/$file")içinis_dir("$dir/$file") && !is_link("$dir/$file")
Kira M. Backes

13

* Nix için a veya Windows shell_execiçin kullanabilirsiniz .rm -RDEL /S folder_name


2
DEL /S folder_nameWindows için ne dersiniz
ankitjaininfo

@Bordon RMDIR /S /Q folder_namebenim için çalıştı
Brian Leishman

2
@ WiR3D exec komutu kullanıcı girişi içermediği sürece iyi olmalısınız. Örn:exec('rm -rf ' . __DIR__ . '/output/*.log');
Brian Hannay

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

Oldukça karmaşık öneri ;-)
Philipp

@Philipp evet sanırım. Ben gist.github.com/mindplay-dk/a4aad91f5a4f1283a5e2 dışında bir çatal yaptım çünkü işe yaramadım, bu yüzden sadece paylaşabileceğimi düşündüm.
XzaR

Bir sorun var. Tüm dosyalar kaldırıldıktan sonra boş klasörleri silmez. Biraz değiştirilmiş versiyonu aşağıdaki cevap olarak gönderiyoruz.
Vladislav Rastrusny

@Vladislav Rastrusny gerçekten mi? Benim için çalışıyor. Belki salt okunur veya başka bir şey içeren bir klasörünüz vardı.
XzaR


1

çalışan ve on yaşında okuyabilen 'basit' kod:

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

Yaptığım tüm genişletin / basitleştirmek ve düzeltmek olduğunu unutmayın (boş olmayan dir için işe yaramadı) burada çözüm: PHP boş olmayan tüm klasörleri özyinelemeli olarak nasıl kaldırabilirim?


1

@Artefacto'nun çözümü - düzeltilmiş yazım hataları ve basitleştirilmiş kod, hem boş hem de boş olmayan dizinler için çalışıyor.

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

1

% 100 çalışma çözümü

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

0

Böyle bir şey mi?

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

Nedenini açıklayamıyorum ama bu benim için işe yaramadı. Boş olmayan bir klasörü silmeye çalışıyordu. Yukarıdaki ikinci cevap işe yaradı.
laurent

1
@ buggy3 Hangi özel koda atıfta bulunuyorsunuz? Bağlantı basitçe bu soru sayfasına bağlanır.
cgogolin

0

Glob () işlevine sahip örnek . Nokta ile başlayan dosyalar da dahil olmak üzere tüm dosya ve klasörleri tekrar tekrar siler.

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

Ben gittimsystem('rm -fr folder')
Itay Moav -Malimovka

0

unlinkr işlevi, komut dosyasının kendisini silmediğinden emin olarak verilen yoldaki tüm klasörleri ve dosyaları yinelemeli olarak siler.

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

bu komut dosyasını yerleştirdiğiniz tüm dosya ve klasörleri silmek istiyorsanız aşağıdaki gibi adlandırın

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

Sadece php dosyalarını silmek istiyorsanız aşağıdaki gibi çağırın

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

dosyaları silmek için başka bir yol da kullanabilirsiniz

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

Bu, home / user / temp dizinindeki tüm dosyaları silecektir.


0

Bu kodu kullanıyorum ...

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

ya da bu...

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

Bu özyinelemeli mi?
Martin Tournoij

0

Eğer testler tamamladıktan sonra, sadece # kaldırmak gelen #Unlink ve #rmdir sınıfında.

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

?>

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

?>

cleanup.php:

<?php

/* include.. */

filesystem::rrmdir('/var/log');
filesystem::rrmdir('./cache');

?>

0

Diğer tüm cevaplar, işleve verilen yolun her zaman bir dizin olduğunu varsayar. Bu varyant, dizinleri ve tek dosyaları kaldırmak için çalışır:

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

0

DirectoryIterator ve özyinelemeyi doğru kullanma:

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

-1

Ben juste bazı StackOverflow tartışmalardan, bu kodu yaptı. Henüz Linux ortamında test yapmadım. Bir dosyayı veya dizini tamamen silmek için yapılır:

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

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

}

-1

@XzaR çözeltisinin değiştirilmiş çeşidi. Tüm dosyalar onlardan silindiğinde boş klasörleri kaldırır ve hatalarda yanlış döndürmek yerine istisnalar atar.

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

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

1
Kabul edilmiş bir soru da dahil olmak üzere çok sayıda yanıtı olan eski bir soruyu yanıtlıyorsanız, yanıtınızın yalnızca kod değil, kattığı katma değerin bir açıklamasını göndermeniz gerekir. Yalnızca kod yanıtları genel olarak, ancak özellikle bu durumda kaşlarını çatmaktadır.
Jared Smith

Bu cevaba oy verdim ve yanıtı kabul ettim. Bu benim kıyaslama onay alındı (olmadan, kötü değil unlink, rmdir) opendir+ readdirişlerinizi daha hızlı olduğunu scandirve RecursiveDirectoryIteratoraynı zamanda tümünden daha az bellek kullanmak edilir. closedirÖnce benim klasör kaldırmak için , bu sıkışmış. Bu cevap için teşekkürler.
vee
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.