PHP: Unlink All Files Within A Directory, and then Deleting That Directory
Asked Answered
N

9

36

Is there any way I can use RegExp or Wildcard searches to quickly delete all files within a folder, and then remove that folder in PHP, WITHOUT using the "exec" command? My server does not give me authorization to use that command. A simple loop of some kind would suffice.

I need something that would accomplish the logic behind the following statement, but obviously, would be valid:

$dir = "/home/dir"
unlink($dir . "/*"); # "*" being a match for all strings
rmdir($dir);
Naara answered 29/6, 2012 at 18:28 Comment(2)
#3350253Inch
#3338623Eupatrid
A
86

Use glob to find all files matching a pattern.

function recursiveRemoveDirectory($directory)
{
    foreach(glob("{$directory}/*") as $file)
    {
        if(is_dir($file)) { 
            recursiveRemoveDirectory($file);
        } else {
            unlink($file);
        }
    }
    rmdir($directory);
}
Anemic answered 29/6, 2012 at 18:32 Comment(6)
I got an error maximum function nesting level of '100' reachedIsborne
I was having permission issues with a scandir function in my code, now it works perfectly with this version!Iaverne
glob takes care of hidden files?Mertens
awesome solution :DRecognizance
Instead of just } else { use } else if(!is_link($file)) { to be symlink safeAnia
Be careful with glob and large number of files. It could consume a lot of memory and result in performance problems under certain conditions.Ceramics
W
18

Use glob() to easily loop through the directory to delete files then you can remove the directory.

foreach (glob($dir."/*.*") as $filename) {
    if (is_file($filename)) {
        unlink($filename);
    }
}
rmdir($dir);
Wobbling answered 29/6, 2012 at 18:33 Comment(1)
this code is dangerous, path should be included in the glob like so glob($dir."/*.*"). i tried it and it wiped out all the directory including top ones my hard workIsborne
L
10

The glob() function does what you're looking for. If you're on PHP 5.3+ you could do something like this:

$dir = ...
array_walk(glob($dir . '/*'), function ($fn) {
    if (is_file($fn))
        unlink($fn);
});
unlink($dir);
Liberalism answered 29/6, 2012 at 18:36 Comment(0)
I
9

A simple and effective way of deleting all files and folders recursively with Standard PHP Library, to be specific, RecursiveIteratorIterator and RecursiveDirectoryIterator. The point is in RecursiveIteratorIterator::CHILD_FIRST flag, iterator will loop through files first, and directory at the end, so once the directory is empty it is safe to use rmdir().

foreach( new RecursiveIteratorIterator( 
    new RecursiveDirectoryIterator( 'folder', FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS ), 
    RecursiveIteratorIterator::CHILD_FIRST ) as $value ) {
        $value->isFile() ? unlink( $value ) : rmdir( $value );
}

rmdir( 'folder' );
Intumescence answered 24/3, 2015 at 20:4 Comment(1)
This is a beautiful answer from almost 10 years ago... I love the RecursiveIteratorIterator and RecursiveDirectoryIterator implementation in PHP because not only they are standard and safe,m but also fast and clean. This should be the one answer that everyone uses! This is a beautiful answer from almost 10 years ago... I love the RecursiveIteratorIterator and RecursiveDirectoryIterator implementation in PHP because not only they are standard and safe, but also fast and clean. This should be the one answer that everyone uses!Egyptology
S
6

Try easy way:

$dir = "/home/dir";
array_map('unlink', glob($dir."/*"));
rmdir($dir);

In Function for remove dir:

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('..', '.')))  {
                unlinkr($file, $pattern);
                //remove the directory itself
                rmdir($file);
                } else if(is_file($file) and ($file != __FILE__)) {
                // make sure you don't delete the current script
                unlink($file); 
            }
        }
        rmdir($dir);
    }

//call following way:
unlinkr("/home/dir");
Squalor answered 12/3, 2015 at 10:21 Comment(1)
While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.Intine
R
4

You can use the Symfony Filesystem component, to avoid re-inventing the wheel, so you can do

use Symfony\Component\Filesystem\Filesystem;

$filesystem = new Filesystem();

if ($filesystem->exists('/home/dir')) {
    $filesystem->remove('/home/dir');
}

If you prefer to manage the code yourself, here's the Symfony codebase for the relevant methods

class MyFilesystem
{
    private function toIterator($files)
    {
        if (!$files instanceof \Traversable) {
            $files = new \ArrayObject(is_array($files) ? $files : array($files));
        }

        return $files;
    }

    public function remove($files)
    {
        $files = iterator_to_array($this->toIterator($files));
        $files = array_reverse($files);
        foreach ($files as $file) {
            if (!file_exists($file) && !is_link($file)) {
                continue;
            }

            if (is_dir($file) && !is_link($file)) {
                $this->remove(new \FilesystemIterator($file));

                if (true !== @rmdir($file)) {
                    throw new \Exception(sprintf('Failed to remove directory "%s".', $file), 0, null, $file);
                }
            } else {
                // https://bugs.php.net/bug.php?id=52176
                if ('\\' === DIRECTORY_SEPARATOR && is_dir($file)) {
                    if (true !== @rmdir($file)) {
                        throw new \Exception(sprintf('Failed to remove file "%s".', $file), 0, null, $file);
                    }
                } else {
                    if (true !== @unlink($file)) {
                        throw new \Exception(sprintf('Failed to remove file "%s".', $file), 0, null, $file);
                    }
                }
            }
        }
    }

    public function exists($files)
    {
        foreach ($this->toIterator($files) as $file) {
            if (!file_exists($file)) {
                return false;
            }
        }

        return true;
    }
}
Rechabite answered 9/1, 2015 at 14:7 Comment(0)
U
1

One way of doing it would be:

function unlinker($file)
{
    unlink($file);
}
$files = glob('*.*');
array_walk($files,'unlinker');
rmdir($dir);
Unify answered 29/6, 2012 at 18:35 Comment(0)
S
0

without creating an array first, definitely faster. sometimes it takes special handling why a folder cannot be deleted.

function clean_dir($dir){
        $error='';
        $dh=opendir($dir);
        while($dh&&($file=readdir($dh))!=false){
            if($file=='.'||$file=='..')continue;
            $rp=$dir=='.'?$file:"$dir/$file";
            if(!is_readable($rp)){$error.=PHP_EOL.$rp;continue;}
            if(is_link($rp))@unlink(readlink($rp));
            elseif(is_file($rp))
            chmod($rp,octdec(644))!=false?@unlink($rp):$error.=PHP_EOL.$rp;
            elseif(is_dir($rp)){
                if(chmod($rp,octdec(755))!=false)
                    count(scandir($rp))==2?@rmdir($rp):clean_dir($rp);
                else{$error.=PHP_EOL.$rp;}
            }
        }
        closedir($dh);
        return($error);
    }
Sidwell answered 11/7, 2023 at 23:47 Comment(0)
G
-1

for removing all the files you can remove the directory and make again.. with a simple line of code

<?php 
    $dir = '/home/files/';
    rmdir($dir);
    mkdir($dir);
?>
Ginglymus answered 20/11, 2017 at 9:40 Comment(1)
you can't rmdir() a non empty directory, this is literally the reason for this threadButters

© 2022 - 2024 — McMap. All rights reserved.