306

I wonder, what's the easiest way to delete a directory with all its files in it?

I'm using rmdir(PATH . '/' . $value); to delete a folder, however, if there are files inside of it, I simply can't delete it.

Nick
  • 4,302
  • 2
  • 24
  • 38
matt
  • 42,713
  • 103
  • 264
  • 397
  • 14
    possible duplicate of [How do I delete a directory and its entire contents (files+sub dirs) in PHP?](http://stackoverflow.com/questions/3338123/how-do-i-delete-a-directory-and-its-entire-contents-filessub-dirs-in-php) – Artefacto Jul 28 '10 at 03:45
  • 2
    yup, answered exactly in that question. – timdev Jul 28 '10 at 03:46
  • Just want to note. I created multiple files and if during the process get some error, then need to delete the previously created files. When created files, forgot to use `fclose($create_file);` and when delete, got `Warning: unlink(created_file.xml): Permission denied in...`. So to avoid such errors must close created files. – Andris Apr 14 '15 at 03:47
  • Possible duplicate of [How do I recursively delete a directory and its entire contents (files + sub dirs) in PHP?](https://stackoverflow.com/questions/3338123/how-do-i-recursively-delete-a-directory-and-its-entire-contents-files-sub-dir) – Fifi Aug 06 '19 at 12:50

34 Answers34

443

There are at least two options available nowadays.

  1. Before deleting the folder, delete all its files and folders (and this means recursion!). Here is an example:

    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. And if you are using 5.2+ you can use a RecursiveIterator to do it without implementing the recursion yourself:

    $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);
    
jla
  • 4,191
  • 3
  • 27
  • 44
alcuadrado
  • 8,340
  • 3
  • 24
  • 25
  • 16
    Your second implementation is somewhat dangerous: it doesn't check for dots (`.` and `..`) and it deletes the resolved path, not the actual one. – Alix Axel Jun 01 '11 at 07:53
  • I've tweaked this answer, as `RecursiveDirectoryIterator` doesn't require PHP 5.3. – halfer Jun 03 '12 at 11:39
  • 10
    little add-on :-) glob() does not support files like .htaccess. I used the function to clear directories made by KCFinder (CKEditor plugin) which generates both .htaccess and .thumbs (file + folder). Instead I used the `scandir` function to get the folder list. Just make sure you filter the '.' and '..' files from the result list. – Joshua - Pendo Jun 18 '12 at 17:23
  • 1
    Editted your answer, just waiting to be reviewed :) – Joshua - Pendo Jun 21 '12 at 08:52
  • 28
    DIRECTORY_SEPARATOR is not necessary when you're building paths to send _to_ the os. Windows will accept forward slashes too. Its mainly useful for `explode()`ing a path taken _from_ the OS. http://alanhogan.com/tips/php/directory-separator-not-necessary – ReactiveRaven Jul 16 '12 at 23:47
  • Your second solution using iterators works but it doesn't delete the directory itself (just its contents). So an additional call to `rmdir` after the foreach loop is necessary. Otherwise, good job. – Robert Audi Aug 11 '12 at 16:03
  • The second example still does not always delete all sub-folders. For example I tested on a folder that had several subfolders and files which all also had subfolders and files. After the first run it deleted everything except the top level folder and left and subfolders in it, the subfolders are now empty though. SO I had to refresh the page a few times to get it to delete all the fsubfolders – JasonDavis Jun 01 '13 at 14:14
  • For the second solution, it doesn't work if you have a lot of sub directories that have their own directories including files. – Ms01 Oct 13 '13 at 21:51
  • Please add is_array check to $files variable before using it in a foreach. – agwntr Mar 12 '15 at 20:10
  • change your glob impl to "$files = glob($dirPath . '{,.}*', GLOB_BRACE);" and check for dots in last-pos of file-name (and continue those) -> and this method can handle hidden files nicely... thx for the base-impl :) – jebbie May 20 '15 at 14:50
  • 8
    In addition to @Alix Axel Using here the [SplFileInfo::getRealPath()] (http://php.net/manual/en/splfileinfo.getrealpath.php) is not a good idea. This method expands all symbolic links, that means, will be deleted a real file from somewhere instead a symlink from the target directory. You should use SplFileInfo::getPathname() instead. – Vijit Jun 03 '16 at 09:58
  • `glob($dirPath . '{,.}[!.,!..]*',GLOB_BRACE)` will skips `./` and `../` but keeps dot-files. – Nick Tsai Jun 26 '17 at 10:44
  • 4
    I agree with @Vijit, use getPathname() instead of getRealPath(). It does the same thing without deleting more than what you are expecting to if symlinks are found. – JoeMoe1984 Sep 22 '17 at 23:49
  • @agwntr That wouldn't work. `$files` isn't an array here, it's an instance of `RecursiveIteratorIterator`. – Eborbob May 14 '18 at 13:55
  • 1
    First solution doesn't seem to delete hidden files (namely `.DS_Store` files in macOS), so deleting the directory fails at the end. – Andy Ibanez May 12 '19 at 02:05
  • 1
    ErrorException : rmdir(public/docs/source/): Directory not empty – Даниил Пронин Dec 03 '19 at 04:05
  • If you can't execute `rmdir()` at the end of the second implementation, you could try adding `$ri->endIteration();` right before it. – lolsky Jan 27 '20 at 20:28
  • On PHP7+ this snippet leads to an E_COMPILE_ERROR: "Cannot use "self" when no class scope is active" – Dnl Feb 18 '20 at 15:37
  • RecursiveDirectoryIterator doesn't require PHP 5.3. But SKIP_DOTS does – vp_arth Jul 10 '20 at 11:06
264

I generally use this to delete all files in a folder:

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

And then you can do

rmdir($dirname);
user3033886
  • 2,815
  • 1
  • 12
  • 7
  • 41
    This doesn't delete folders recursively; it only works if the folder has only regular files in it, all of which have file extensions. – mgnb Jul 09 '15 at 02:04
  • 12
    If no recursion is needed this is the best and simpliest answer so far. Thanks! – eisbehr Oct 31 '16 at 09:09
  • 7
    In order to remove *all* files from a folder, not only the ones with extensions, use glob in the following way: `array_map('unlink', glob("$dirname/*"));` This still doesn't allow you to delete directories nested in the folder. – kremuwa Apr 09 '18 at 09:21
  • 1
    Note that this will remove dot (hidden) files as well. – BadHorsie Sep 26 '19 at 13:39
  • To delete folders recursively, just do `array_map("unlink", glob("$dirname/*")); array_map("rmdir", glob("$dirname/*")); rmdir($dirname);`. – Madeorsk Jun 29 '21 at 17:55
107

what's the easiest way to delete a directory with all its files in it?

system("rm -rf ".escapeshellarg($dir));
danronmoon
  • 3,814
  • 5
  • 34
  • 56
Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
  • 58
    I hope you're not serious. What happens if $dir is / – The Pixel Developer Jul 28 '10 at 04:46
  • 143
    @The exactly the same as with any of the codes above. Isn't it? – Your Common Sense Jul 28 '10 at 08:33
  • 12
    Note that, depending how `$dir` is generated/provided, you may need to do some additional pre-processing to be safe and to avoid bugs. For example, if `$dir` might have an unescaped space or semi-colon in it, then there could be undesirable side effects. This is not the case with the answers that use things like `rmdir()` because it will handle the special characters for you. – Trott Mar 03 '12 at 22:12
  • 8
    Windows version: `system('rmdir '.escapeshellarg($path).' /s /q');` – Cypher Jan 19 '14 at 02:03
  • 1
    At the very least you should explain some caveats for such a dangerous answer. `$dir` needs to be sanitized, it's unix-specific, it relies on something many sysadmins disallow (shelling out a command), etc. This is the "easiest" solution only when very specific conditions are met. – Nerdmaster Feb 07 '14 at 20:57
  • 2
    @ThePixelDeveloper you shouldn't worry about deleting /, this would only work if you'd lounch the script in command line as root, because in web everything happens as apache user – Ben Jun 27 '14 at 09:40
  • http://security.stackexchange.com/questions/1382/disable-insecure-dangerous-php-functions – markus May 04 '16 at 21:02
  • 1
    How is this not heavily downvoted? Isn't it bad practice to use `system`? – FluorescentGreen5 Aug 10 '17 at 13:53
  • @YourCommonSense It's platform dependent, can be insecure (I know you can escape the arguments, but it's still safer to use pure PHP to accomplish this), and hosting companies would have most likely disabled it. – FluorescentGreen5 Aug 10 '17 at 16:18
  • 2
    @FluorescentGreen5 OK fair. Let's call it a niche solution. Personally, I cannot imagine PHP running on any OS other than Linux and I forgot the time I was using a shared hosting. – Your Common Sense Aug 10 '17 at 16:23
  • 7
    @ThePixelDeveloper If your PHP script has access to delete files/folders in root directory, you have serious problems anyway. – Márton Tamás Oct 13 '18 at 14:49
  • 2
    I like this answer more than the others, it's only problem is the Linux dependency, and for the security problem, it's the caller job to check if it is really the intended directory or not, the function's only job is to *delete a directory* . – Accountant م Apr 22 '19 at 22:41
  • perfect one-liner! but because this is OS dependent, it's not universal, thus not preferable for me. – Taufik Nur Rahmanda Dec 26 '19 at 23:36
  • thank you do this work in shared host? – Vahid Alvandi Jul 16 '22 at 18:16
  • $dir is what you let it to be, for those with so many caveats about using this approach. – lisandro Jun 29 '23 at 01:49
56

Short function that does the job:

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

I use it in a Utils class like this:

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

With great power comes great responsibility: When you call this function with an empty value, it will delete files starting in root (/). As a safeguard you can check if path is empty:

function deleteDir($path) {
    if (empty($path)) { 
        return false;
    }
    return is_file($path) ?
            @unlink($path) :
            array_map(__FUNCTION__, glob($path.'/*')) == @rmdir($path);
}
Blaise
  • 13,139
  • 9
  • 69
  • 97
  • 1
    The static one doesn't work because $this === NULL when you call a static function on a class. It would work if `$this_func = array(__CLASS__, __FUNCTION__);` – Matt Connolly Jul 26 '12 at 02:09
  • 2
    Can someone explain the line `array_map($class_func, glob($path.'/*')) == @rmdir($path)`? I guess he's recursing through the subfolders, but what does the == @rmdir part do? How does the == return the answer? Does it check if each return value of the recursion is the same as the boolean on the right? – arviman Jan 06 '13 at 23:32
  • 2
    It's a trick to merge two statements into one statement. This is because ternary operators allow only one statement per argument. `array_map(...)` removes all files within the directory, `@rmdir(...)` removes the directory itself. – Blaise Jan 07 '13 at 09:57
  • 3
    Be careful! This function does not check if the path really exists. If you pass an empty argument, the function will start to delete files starting from the root! Add a sanity check to your path before you run this function. – Tatu Ulmanen Oct 24 '14 at 13:34
  • 3
    Some people did not see Tatu's comment and recursively deleted `/`, so I appended a safeguarded version to my post. – Blaise Nov 26 '14 at 10:25
  • Sorry but... I still not understanding the operation of the last line with array_map... – Pedro Antônio May 22 '19 at 14:42
  • @PedroAntônio `array_map` calls a function (first argument) for each item returned by the glob and then continues to delete the dir itself in `@rmdir`. – Blaise May 22 '19 at 15:00
38

As seen in most voted comment on PHP manual page about rmdir() (see http://php.net/manual/es/function.rmdir.php), glob() function does not return hidden files. scandir() is provided as an alternative that solves that issue.

Algorithm described there (which worked like a charm in my case) is:

<?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); 
    } 
?>
German Latorre
  • 10,058
  • 14
  • 48
  • 59
  • can you please explain is_dir("$dir/$file") - did not meet with the "$dir/$file" parameter – Igor L. Sep 17 '15 at 10:20
  • What do you mean? It checks if the entry found in a directory (`$file`) is a directory or a file. `"$dir/$file"` is the same as `$dir . "/" . $file`. – German Latorre Sep 17 '15 at 11:41
  • I honestly did not know you can concatenate variables like this :) thx – Igor L. Sep 17 '15 at 12:51
  • The only challenge I came across with this example is that it doesn't handle symlinks to directories vary well within the directory. To do this, change the is_dir check to `(is_dir("$dir/$file") && !is_link("$dir/$file"))` – General Redneck Jun 25 '21 at 15:37
23

You may use Symfony's Filesystem (code):

// composer require symfony/filesystem

use Symfony\Component\Filesystem\Filesystem;

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

However I couldn't delete some complex directory structures with this method, so first you should try it to ensure it's working properly.


I could delete the said directory structure using a Windows specific implementation:

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


And just for the sake of completeness, here is an old code of mine:

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);
}
Gras Double
  • 15,901
  • 8
  • 56
  • 54
19

This is a shorter Version works great to me

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);
    }
}
user6972
  • 851
  • 1
  • 15
  • 32
Playnox
  • 1,087
  • 14
  • 9
15

You can try as follows:

/*
 * 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);
        }
    }
}
Bablu Ahmed
  • 4,412
  • 5
  • 49
  • 64
13

I can't believe there are 30+ answers for this. Recursively deleting a folder in PHP could take minutes depending on the depth of the directory and the number of files in it! You can do this with one line of code ...

shell_exec("rm -rf " . $dir);

If you're concerned with deleting the entire filesystem, make sure your $dir path is exactly what you want first. NEVER allow a user to input something that can directly delete files without first heavily validating the input. That's essential coding practice.

WebTigers
  • 297
  • 2
  • 8
  • I am doing clean up on the /tmp folder so ```shell_exec("rm -rf " . sys_get_temp_dir() . "/{$dir}");``` is easy, straight forward and lighting fast. – Francisco Luz Sep 04 '21 at 19:08
  • 2
    This! but I would do `shell_exec("rm -rf '$dir'");` – Eli Algranti Oct 09 '21 at 10:27
  • I'm using this with a cron job to remove uploaded security camera images from the previous day. Obviously as stated above don't let users have access to this and make sure you got your $dir correct! – drooh Mar 31 '22 at 20:56
  • Not everyone has access to `shell_exec()`, but if you do then this would be the way to go. – Kerry Johnson Oct 05 '22 at 20:56
12

This one works for me:

function removeDirectory($path) {
    $files = glob($path . '/*');
    foreach ($files as $file) {
        is_dir($file) ? removeDirectory($file) : unlink($file);
    }
    rmdir($path);
    return;
}
Christopher Smit
  • 953
  • 11
  • 27
10

Here you have one nice and simple recursion for deleting all files in source directory including that directory:

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

}

Function is based on recursion made for copying directory. You can find that function here: Copy entire contents of a directory to another using php

Community
  • 1
  • 1
Tommz
  • 3,393
  • 7
  • 32
  • 44
7

The Best Solution for me

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

code:

function my_folder_delete($path) {
    if (in_array($path, ['.', '/'])) return; // ensure to avoid accidents
    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);
    }
}

p.s. REMEMBER!
dont pass EMPTY VALUES to any Directory deleting functions!!! (backup them always, otherwise one day you might get DISASTER!!)

T.Todua
  • 53,146
  • 19
  • 236
  • 237
5

Glob function doesn't return the hidden files, therefore scandir can be more useful, when trying to delete recursively a tree.

<?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);
  }
?>
candlejack
  • 1,189
  • 2
  • 22
  • 51
5

Example for the Linux server: exec('rm -f -r ' . $cache_folder . '/*');

realmag777
  • 2,050
  • 1
  • 24
  • 22
  • I usually like to add a sanity check on $cache_folder before running rm -rf to avoid costly mistakes – 111 Mar 31 '20 at 19:08
4

Litle bit modify of alcuadrado's code - glob don't see files with name from points like .htaccess so I use scandir and script deletes itself - check __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);
}
karma_police
  • 332
  • 2
  • 14
4

I want to expand on the answer by @alcuadrado with the comment by @Vijit for handling symlinks. Firstly, use getRealPath(). But then, if you have any symlinks that are folders it will fail as it will try and call rmdir on a link - so you need an extra check.

$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);
user701152
  • 51
  • 2
3

I prefer this because it still returns TRUE when it succeeds and FALSE when it fails, and it also prevents a bug where an empty path might try and delete everything from '/*' !!:

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);
}
Matt Connolly
  • 9,757
  • 2
  • 65
  • 61
3

What about this:

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);
}
adrian
  • 111
  • 3
  • 11
3

Using DirectoryIterator an equivalent of a previous answer…

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);
}
Alan Trewartha
  • 131
  • 1
  • 4
3

you can try this simple 12 line of code for delete folder or folder files... happy coding... ;) :)

function deleteAll($str) {
    if (is_file($str)) {
        return unlink($str);
    }
    elseif (is_dir($str)) {
        $scan = glob(rtrim($str,'/').'/*');
        foreach($scan as $index=>$path) {
            $this->deleteAll($path);
        }            
        return @rmdir($str);
    }
}
Adeel Ahmed Baloch
  • 672
  • 2
  • 7
  • 15
2

Something like this?

function delete_folder($folder) {
    $glob = glob($folder);
    foreach ($glob as $g) {
        if (!is_dir($g)) {
            unlink($g);
        } else {
            delete_folder("$g/*");
            rmdir($g);
        }
    }
}
Kerem
  • 11,377
  • 5
  • 59
  • 58
1

Delete all files in Folder
array_map('unlink', glob("$directory/*.*"));
Delete all .*-Files in Folder (without: "." and "..")
array_map('unlink', array_diff(glob("$directory/.*),array("$directory/.","$directory/..")))
Now delete the Folder itself
rmdir($directory)

PP2000
  • 11
  • 1
1

2 cents to add to THIS answer above, which is great BTW

After your glob (or similar) function has scanned/read the directory, add a conditional to check the response is not empty, or an invalid argument supplied for foreach() warning will be thrown. So...

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

My full function (as an object method):

    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()
Community
  • 1
  • 1
Phil Meadows
  • 23
  • 1
  • 6
1

Here is the solution that works perfect:

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;
}
Tarik
  • 4,270
  • 38
  • 35
1

What about this?

function Delete_Directory($Dir) 
{
  if(is_dir($Dir))
  {
      $files = glob( $Dir . '*', GLOB_MARK ); //GLOB_MARK adds a slash to directories returned

      foreach( $files as $file )
      {
          Delete_Directory( $file );      
      }
      if(file_exists($Dir))
      {
          rmdir($Dir);
      }
  } 
  elseif(is_file($Dir)) 
  {
     unlink( $Dir );  
  }
}

Refrence: https://paulund.co.uk/php-delete-directory-and-files-in-directory

Mohamad Hamouday
  • 2,070
  • 23
  • 20
1

You could copy the YII helpers

$directory (string) - to be deleted recursively.

$options (array) - for the directory removal. Valid options are: traverseSymlinks: boolean, whether symlinks to the directories should be traversed too. Defaults to false, meaning that the content of the symlinked directory would not be deleted. Only symlink would be removed in that default case.

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);
    }
}
José Veríssimo
  • 221
  • 2
  • 11
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);
  }
 }
?>

Have your tryed out the obove code from php.net

Work for me fine

Gaurang
  • 1,928
  • 18
  • 12
0

For windows:

system("rmdir ".escapeshellarg($path) . " /s /q");
Mylo
  • 65
  • 1
  • 1
  • 6
0

Like Playnox's solution, but with the elegant built-in DirectoryIterator:

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!');
  }
 }
Matthew Slyman
  • 346
  • 3
  • 9
0

I do not remember from where I copied this function, but it looks like it is not listed and it is working for me

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);
    }
}
dav
  • 8,931
  • 15
  • 76
  • 140
0

Simple and Easy...

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

If you are not sure, Given path is directory or file then you can use this function to delete path

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;
        }
}
jay padaliya
  • 624
  • 6
  • 12
-1

Here is a simple solution

$dirname = $_POST['d'];
    $folder_handler = dir($dirname);
    while ($file = $folder_handler->read()) {
        if ($file == "." || $file == "..")
            continue;
        unlink($dirname.'/'.$file);

    }
   $folder_handler->close();
   rmdir($dirname);
Andy Obusek
  • 12,614
  • 4
  • 41
  • 62
majo
  • 11
-5

Platform independent code.

Took the answer from PHP.net

if(PHP_OS === 'Windows')
{
 exec("rd /s /q {$path}");
}
else
{
 exec("rm -rf {$path}");
}
mysticmo
  • 47
  • 3