İçindeki dosyaları içeren dizin silinsin mi?


246

Acaba, içindeki tüm dosyaları içeren bir dizini silmenin en kolay yolu nedir?

rmdir(PATH . '/' . $value);Bir klasörü silmek için kullanıyorum , ancak içinde dosyalar varsa, onu silemiyorum.



2
evet, tam olarak bu soruya cevap verdi.
timdev

Sadece not etmek istiyorum. Birden fazla dosya oluşturdum ve işlem sırasında bir hata alırsanız, önceden oluşturulan dosyaları silmeliyim. Dosyalar oluşturulduğunda, kullanmayı unuttum fclose($create_file);ve sildiğimde aldım Warning: unlink(created_file.xml): Permission denied in.... Yani bu tür hatalardan kaçınmak için oluşturulan dosyaları kapatmalısınız.
Andris

Yanıtlar:


382

Bugünlerde en az iki seçenek mevcut.

  1. Klasörü silmeden önce, tüm dosyalarını ve klasörlerini silin (ve bu özyineleme anlamına gelir!). İşte bir örnek:

    public static function deleteDir($dirPath) {
        if (! is_dir($dirPath)) {
            throw new InvalidArgumentException("$dirPath must be a directory");
        }
        if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') {
            $dirPath .= '/';
        }
        $files = glob($dirPath . '*', GLOB_MARK);
        foreach ($files as $file) {
            if (is_dir($file)) {
                self::deleteDir($file);
            } else {
                unlink($file);
            }
        }
        rmdir($dirPath);
    }
  2. 5.2+ kullanıyorsanız, yinelemeyi kendiniz uygulamadan bunu yapmak için bir RecursiveIterator kullanabilirsiniz:

    $dir = 'samples' . DIRECTORY_SEPARATOR . 'sampledirtree';
    $it = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS);
    $files = new RecursiveIteratorIterator($it,
                 RecursiveIteratorIterator::CHILD_FIRST);
    foreach($files as $file) {
        if ($file->isDir()){
            rmdir($file->getRealPath());
        } else {
            unlink($file->getRealPath());
        }
    }
    rmdir($dir);

11
İkinci uygulamanız biraz tehlikelidir: noktaları ( .ve ..) kontrol etmez ve asıl olanı değil, çözülmüş yolu siler.
Alix Axel

9
küçük eklenti :-) glob () .htaccess gibi dosyaları desteklemez. Bu işlevi, .htaccess ve .thumbs (dosya + klasör) üreten KCFinder (CKEditor eklentisi) tarafından yapılan dizinleri temizlemek için kullandım. Bunun yerine scandirklasör listesini almak için işlevi kullandım . '' Filtresini filtrelediğinizden emin olun. ve sonuç listesinden '..' dosyaları.
Joshua - Pendo

25
İşletim sistemine göndermek için yollar oluştururken DIRECTORY_SEPARATOR gerekli değildir . Windows eğik çizgileri de kabul eder. Onun esas kullanışlı explode()alınan bir yolunu ing den OS. alanhogan.com/tips/php/directory-separator-not-necessary
ReactiveRaven

5
@Alix Axel'e ek olarak Burada [SplFileInfo :: getRealPath ()] ( php.net/manual/en/splfileinfo.getrealpath.php ) kullanımı iyi bir fikir değildir. Bu yöntem tüm sembolik bağlantıları genişletir, yani hedef dizinden bir sembolik bağlantı yerine gerçek bir dosyayı bir yerden siler. Bunun yerine SplFileInfo :: getPathname () kullanmalısınız.
Vijit

2
@Vijit ile hemfikirim, getRealPath () yerine getPathname () kullanın. Aynı şey, semboller bulunursa beklediğinizden daha fazlasını silmeden yapar.
JoeMoe1984

196

Ben genellikle bir klasördeki tüm dosyaları silmek için kullanın:

array_map('unlink', glob("$dirname/*.*"));

Ve sonra yapabilirsin

rmdir($dirname);

27
Bu klasörleri özyinelemeli olarak silmez; yalnızca klasörde yalnızca dosya uzantıları olan normal dosyalar varsa çalışır.
mgnb

5
Özyineleme gerekmiyorsa, bu şimdiye kadarki en iyi ve en basit cevaptır. Teşekkürler!
eisbehr

2
Yalnızca uzantıları olanları değil, bir klasördeki tüm dosyaları kaldırmak için glob'u şu şekilde kullanın: array_map('unlink', glob("$dirname/*"));Bu, klasörde bulunan dizinleri silmenize izin vermez.
kremuwa

Bunun nokta (gizli) dosyaları da kaldıracağını unutmayın.
BadHorsie

84

içindeki tüm dosyaları içeren bir dizini silmenin en kolay yolu nedir?

system("rm -rf ".escapeshellarg($dir));

33
Umarım ciddi değilsin. $ Dir ise ne olur /
Pixel Developer

108
Yukarıdaki kodlardan herhangi biriyle aynıdır. Öyle değil mi?
Ortak Duygunuz

7
Nasıl $dirüretildiğine / sağlandığına bağlı olarak , güvenli olmak ve hataları önlemek için bazı ek ön işlemler yapmanız gerekebileceğini unutmayın. Örneğin, içinde $dirkaçamayan bir boşluk veya noktalı virgül varsa, istenmeyen yan etkiler olabilir. Bunun gibi şeyleri kullanan cevaplarda durum böyle değildir rmdir()çünkü sizin için özel karakterleri işleyecektir.
Trott

5
Windows sürümü:system('rmdir '.escapeshellarg($path).' /s /q');
Cypher

2
@ThePixelDeveloper silme konusunda endişelenmemelisiniz /, bu sadece komut dosyasını komut satırında root olarak kilitlerseniz çalışır, çünkü web'de her şey apache kullanıcısı olarak gerçekleşir
Ben

49

İşi yapan kısa fonksiyon:

function deleteDir($path) {
    return is_file($path) ?
            @unlink($path) :
            array_map(__FUNCTION__, glob($path.'/*')) == @rmdir($path);
}

Ben böyle bir Utils sınıfında kullanın:

class Utils {
    public static function deleteDir($path) {
        $class_func = array(__CLASS__, __FUNCTION__);
        return is_file($path) ?
                @unlink($path) :
                array_map($class_func, glob($path.'/*')) == @rmdir($path);
    }
}

Büyük güçle büyük sorumluluk gelir : Bu işlevi boş bir değerle çağırdığınızda, root ( /) ile başlayan dosyaları siler . Bir koruma olarak, yolun boş olup olmadığını kontrol edebilirsiniz:

function deleteDir($path) {
    if (empty($path)) { 
        return false;
    }
    return is_file($path) ?
            @unlink($path) :
            array_map(__FUNCTION__, glob($path.'/*')) == @rmdir($path);
}

1
Statik çalışmaz, çünkü bir sınıftaki statik işlevi çağırdığınızda $ this === NULL. $this_func = array(__CLASS__, __FUNCTION__);
Olursa

2
Birisi hattı açıklayabilir array_map($class_func, glob($path.'/*')) == @rmdir($path)mi? Sanırım alt klasörler arasında yineleniyor, ancak == @rmdir kısmı ne yapıyor? <Booleans dizisi> == <boolean> yanıtı nasıl döndürür? Özyinelemenin her dönüş değerinin sağdaki boole ile aynı olup olmadığını kontrol ediyor mu?
arviman

2
İki ifadeyi tek bir ifadede birleştirmek hiledir. Bunun nedeni, üçlü işleçlerin bağımsız değişken başına yalnızca bir ifadeye izin vermesidir. array_map(...)dizindeki tüm dosyaları @rmdir(...)kaldırır, dizinin kendisini kaldırır.
Blaise

3
Dikkatli ol! Bu işlev, yolun gerçekten var olup olmadığını kontrol etmez. Boş bir argüman iletirseniz, işlev kökten başlayarak dosyaları silmeye başlar! Bu işlevi çalıştırmadan önce yolunuza bir sağlık kontrolü ekleyin.
Tatu Ulmanen

3
Bazı insanlar Tatu'nun yorumunu görmedi ve yinelemeli olarak silindi /, bu yüzden yazıma korumalı bir versiyon ekledim.
Blaise

22

Hakkında PHP manuel sayfasında en çok oylanan yorumda görüldüğü gibi rmdir()(bkz. Http://php.net/manual/es/function.rmdir.php ), glob()işlev gizli dosyaları döndürmez. scandir()bu sorunu çözen bir alternatif olarak sunulmaktadır.

Orada açıklanan Algoritma (benim durumumda bir cazibe gibi çalıştı):

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

lütfen açıklayabilir misiniz is_dir ("$ dir / $ file") - "$ dir / $ file" parametresi ile tanışmadı
Igor L.

Ne demek istiyorsun? Bir dizinde ( $file) bulunan girişin bir dizin veya dosya olup olmadığını kontrol eder . "$dir/$file"ile aynıdır $dir . "/" . $file.
Alman Latorre

Dürüst olmak gerekirse böyle değişkenleri birleştirebilirsiniz bilmiyordum :) thx
Igor L.

18

Bu daha kısa bir versiyon benim için harika çalışıyor

function deleteDirectory($dirPath) {
    if (is_dir($dirPath)) {
        $objects = scandir($dirPath);
        foreach ($objects as $object) {
            if ($object != "." && $object !="..") {
                if (filetype($dirPath . DIRECTORY_SEPARATOR . $object) == "dir") {
                    deleteDirectory($dirPath . DIRECTORY_SEPARATOR . $object);
                } else {
                    unlink($dirPath . DIRECTORY_SEPARATOR . $object);
                }
            }
        }
    reset($objects);
    rmdir($dirPath);
    }
}

15

Symfony Dosya Sistemini ( kod ) kullanabilirsiniz:

// composer require symfony/filesystem

use Symfony\Component\Filesystem\Filesystem;

(new Filesystem)->remove($dir);

Ancak bu yöntemle bazı karmaşık dizin yapılarını silemedim, bu yüzden önce düzgün çalıştığından emin olmak için denemelisiniz.


Belirtilen dizin yapısını Windows'a özel bir uygulama kullanarak silebilirim:

$dir = strtr($dir, '/', '\\');
// quotes are important, otherwise one could
// delete "foo" instead of "foo bar"
system('RMDIR /S /Q "'.$dir.'"');


Ve sadece bütünlük uğruna, işte eski bir kodum:

function xrmdir($dir) {
    $items = scandir($dir);
    foreach ($items as $item) {
        if ($item === '.' || $item === '..') {
            continue;
        }
        $path = $dir.'/'.$item;
        if (is_dir($path)) {
            xrmdir($path);
        } else {
            unlink($path);
        }
    }
    rmdir($dir);
}

Çok teşekkürler. Zamandan tasarruf edersiniz.
zarif khan

"Tekerleği yeniden icat etme" . Thank you
Kamafeather

9

Burada, bu dizin de dahil olmak üzere kaynak dizindeki tüm dosyaları silmek için bir güzel ve basit özyineleme var:

function delete_dir($src) { 
    $dir = opendir($src);
    while(false !== ( $file = readdir($dir)) ) { 
        if (( $file != '.' ) && ( $file != '..' )) { 
            if ( is_dir($src . '/' . $file) ) { 
                delete_dir($src . '/' . $file); 
            } 
            else { 
                unlink($src . '/' . $file); 
            } 
        } 
    } 
    closedir($dir); 
    rmdir($src);

}

İşlev dizin kopyalamak için yapılan özyinelemeye dayanır. Bu işlevi burada bulabilirsiniz: php kullanarak bir dizinin tüm içeriğini diğerine kopyalayın


4

Benim için En İyi Çözüm

my_folder_delete("../path/folder");

kod:

function my_folder_delete($path) {
    if(!empty($path) && is_dir($path) ){
        $dir  = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS); //upper dirs are not included,otherwise DISASTER HAPPENS :)
        $files = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::CHILD_FIRST);
        foreach ($files as $f) {if (is_file($f)) {unlink($f);} else {$empty_dirs[] = $f;} } if (!empty($empty_dirs)) {foreach ($empty_dirs as $eachDir) {rmdir($eachDir);}} rmdir($path);
    }
}

ps UNUTMAYIN!
herhangi bir Dizin silme işlevlerine BOŞ DEĞERLERİ geçmeyin !!! (onları her zaman yedekleyin, aksi takdirde bir gün AFET alabilirsiniz!)


4

Peki buna ne dersin:

function recursiveDelete($dirPath, $deleteParent = true){
    foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dirPath, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST) as $path) {
        $path->isFile() ? unlink($path->getPathname()) : rmdir($path->getPathname());
    }
    if($deleteParent) rmdir($dirPath);
}

4

Glob işlevi gizli dosyaları döndürmez, bu nedenle scandir bir ağacı özyinelemeli olarak silmeye çalışırken daha yararlı olabilir.

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

4

Aşağıdaki gibi deneyebilirsiniz:

/*
 * Remove the directory and its content (all files and subdirectories).
 * @param string $dir the directory name
 */
function rmrf($dir) {
    foreach (glob($dir) as $file) {
        if (is_dir($file)) { 
            rmrf("$file/*");
            rmdir($file);
        } else {
            unlink($file);
        }
    }
}

3

Bunu tercih ederim çünkü başarılı olduğunda hala DOĞRU ve başarısız olduğunda YANLIŞ döndürür ve aynı zamanda boş bir yolun her şeyi '/ *' den silip silebileceği bir hatayı önler !!

function deleteDir($path)
{
    return !empty($path) && is_file($path) ?
        @unlink($path) :
        (array_reduce(glob($path.'/*'), function ($r, $i) { return $r && deleteDir($i); }, TRUE)) && @rmdir($path);
}

3

Simgelerini işlemek için @Vijit'in yorumuyla @alcuadrado'nun cevabını genişletmek istiyorum. İlk olarak getRealPath () kullanın. Ancak, klasör olan herhangi bir sembol bağlantınız varsa, bir bağlantıda rmdir'i çağırmaya çalışacağından başarısız olur - bu nedenle ekstra bir kontrol yapmanız gerekir.

$it = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
foreach($files as $file) {
    if ($file->isLink()) {
        unlink($file->getPathname());
    } else if ($file->isDir()){
        rmdir($file->getPathname());
    } else {
        unlink($file->getPathname());
    }
}
rmdir($dir);

1
Cevabı doğrudan yorumlamak için yeterli temsilcim yok.
user701152

3

DirectoryIterator'ı önceki bir yanıtın eşdeğeri kullanarak…

function deleteFolder($rootPath)
{   
    foreach(new DirectoryIterator($rootPath) as $fileToDelete)
    {
        if($fileToDelete->isDot()) continue;
        if ($fileToDelete->isFile())
            unlink($fileToDelete->getPathName());
        if ($fileToDelete->isDir())
            deleteFolder($fileToDelete->getPathName());
    }

    rmdir($rootPath);
}

3

Bu benim için çalışıyor:

function removeDirectory($path) {
    $files = glob($path . '/*');
    foreach ($files as $file) {
        is_dir($file) ? removeDirectory($file) : unlink($file);
    }
    rmdir($path);
    return;
}

2

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

2

Alcuadrado kodunu Litle bit değiştirmek - ben scandir kullanın ve komut dosyası kendini siler - globgibi noktalardan adıyla dosyaları görmüyorum ..htaccess__FILE__

function deleteDir($dirPath) {
    if (!is_dir($dirPath)) {
        throw new InvalidArgumentException("$dirPath must be a directory");
    }
    if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') {
        $dirPath .= '/';
    }
    $files = scandir($dirPath); 
    foreach ($files as $file) {
        if ($file === '.' || $file === '..') continue;
        if (is_dir($dirPath.$file)) {
            deleteDir($dirPath.$file);
        } else {
            if ($dirPath.$file !== __FILE__) {
                unlink($dirPath.$file);
            }
        }
    }
    rmdir($dirPath);
}

2

Linux sunucusu için örnek: exec('rm -f -r ' . $cache_folder . '/*');


Genellikle pahalı hataları önlemek için rm -rf çalıştırmadan önce $ cache_folder üzerinde bir sağlık kontrolü eklemek istiyorum
glif

1

Klasördeki tüm dosyaları
array_map('unlink', glob("$directory/*.*"));
sil Tümünü sil. * - Klasördeki Dosyalar (olmadan: "." Ve "..")
array_map('unlink', array_diff(glob("$directory/.*),array("$directory/.","$directory/..")))
Şimdi Klasörün kendisini sil
rmdir($directory)


1

Bu cevaba eklemek için 2 sent , bu harika BTW

Glob (veya benzeri) işleviniz dizini taradıktan / okuduktan sonra, yanıtın boş olup olmadığını kontrol etmek için bir koşul ekleyin veya bir invalid argument supplied for foreach()uyarı atılır. Yani...

if( ! empty( $files ) )
{
    foreach( $files as $file )
    {
        // do your stuff here...
    }
}

Tam işlevim (nesne yöntemi olarak):

    private function recursiveRemoveDirectory( $directory )
    {
        if( ! is_dir( $directory ) )
        {
            throw new InvalidArgumentException( "$directory must be a directory" );
        }

        if( substr( $directory, strlen( $directory ) - 1, 1 ) != '/' )
        {
            $directory .= '/';
        }

        $files = glob( $directory . "*" );

        if( ! empty( $files ) )
        {
            foreach( $files as $file )
            {
                if( is_dir( $file ) )
                {
                    $this->recursiveRemoveDirectory( $file );
                }
                else
                {
                    unlink( $file );
                }
            }               
        }
        rmdir( $directory );

    } // END recursiveRemoveDirectory()

1

İşte mükemmel çalışan çözüm:

function unlink_r($from) {
    if (!file_exists($from)) {return false;}
    $dir = opendir($from);
    while (false !== ($file = readdir($dir))) {
        if ($file == '.' OR $file == '..') {continue;}

        if (is_dir($from . DIRECTORY_SEPARATOR . $file)) {
            unlink_r($from . DIRECTORY_SEPARATOR . $file);
        }
        else {
            unlink($from . DIRECTORY_SEPARATOR . $file);
        }
    }
    rmdir($from);
    closedir($dir);
    return true;
}

1

YII yardımcılarını kopyalayabilirsiniz

$ directory (string) - özyinelemeli olarak silinecek.

$ options (array) - dizinin kaldırılması için. Geçerli seçenekler şunlardır: traverseSymlinks: boolean, dizinlere olan sembolik linklerin de geçilmesi gerekip gerekmediği. Varsayılan olarak false, sembolik bağlanmış dizinin içeriğinin silinmeyeceği anlamına gelir. Bu varsayılan durumda yalnızca sembolik bağlantı kaldırılır.

public static function removeDirectory($directory,$options=array())
{
    if(!isset($options['traverseSymlinks']))
        $options['traverseSymlinks']=false;
    $items=glob($directory.DIRECTORY_SEPARATOR.'{,.}*',GLOB_MARK | GLOB_BRACE);
    foreach($items as $item)
    {
        if(basename($item)=='.' || basename($item)=='..')
            continue;
        if(substr($item,-1)==DIRECTORY_SEPARATOR)
        {
            if(!$options['traverseSymlinks'] && is_link(rtrim($item,DIRECTORY_SEPARATOR)))
                unlink(rtrim($item,DIRECTORY_SEPARATOR));
            else
                self::removeDirectory($item,$options);
        }
        else
            unlink($item);
    }
    if(is_dir($directory=rtrim($directory,'\\/')))
    {
        if(is_link($directory))
            unlink($directory);
        else
            rmdir($directory);
    }
}

0
<?php
  function rrmdir($dir) {
  if (is_dir($dir)) {
    $objects = scandir($dir);
    foreach ($objects as $object) {
      if ($object != "." && $object != "..") {
        if (filetype($dir."/".$object) == "dir") 
           rrmdir($dir."/".$object); 
        else unlink   ($dir."/".$object);
      }
    }
    reset($objects);
    rmdir($dir);
  }
 }
?>

Php.net obove kodu denediniz mi

Benim için iyi çalış


0

Pencereler için:

system("rmdir ".escapeshellarg($path) . " /s /q");

0

Playnox'un çözümü gibi, ancak zarif yerleşik DirectoryIterator ile:

function delete_directory($dirPath){
 if(is_dir($dirPath)){
  $objects=new DirectoryIterator($dirPath);
   foreach ($objects as $object){
    if(!$object->isDot()){
     if($object->isDir()){
      delete_directory($object->getPathname());
     }else{
      unlink($object->getPathname());
     }
    }
   }
   rmdir($dirPath);
  }else{
   throw new Exception(__FUNCTION__.'(dirPath): dirPath is not a directory!');
  }
 }

0

Bu işlevi nereden kopyaladığımı hatırlamıyorum, ancak listelenmemiş gibi görünüyor ve benim için çalışıyor

function rm_rf($path) {
    if (@is_dir($path) && is_writable($path)) {
        $dp = opendir($path);
        while ($ent = readdir($dp)) {
            if ($ent == '.' || $ent == '..') {
                continue;
            }
            $file = $path . DIRECTORY_SEPARATOR . $ent;
            if (@is_dir($file)) {
                rm_rf($file);
            } elseif (is_writable($file)) {
                unlink($file);
            } else {
                echo $file . "is not writable and cannot be removed. Please fix the permission or select a new path.\n";
            }
        }
        closedir($dp);
        return rmdir($path);
    } else {
        return @unlink($path);
    }
}

0

Basit ve kolay...

$dir ='pathtodir';
if (is_dir($dir)) {
  foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) {
    if ($filename->isDir()) continue;
    unlink($filename);
  }
  rmdir($dir);
}


0

Emin değilseniz, Verilen yol dizin veya dosyadır, yolu silmek için bu işlevi kullanabilirsiniz

function deletePath($path) {
        if(is_file($path)){
            unlink($path);
        } elseif(is_dir($path)){
            $path = (substr($path, -1) !== DIRECTORY_SEPARATOR) ? $path . DIRECTORY_SEPARATOR : $path;
            $files = glob($path . '*');
            foreach ($files as $file) {
                deleteDirPath($file);
            }
            rmdir($path);
        } else {
            return false;
        }
}
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.