39

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

9 Answers 9

87

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);
}
Sign up to request clarification or add additional context in comments.

6 Comments

I got an error maximum function nesting level of '100' reached
I was having permission issues with a scandir function in my code, now it works perfectly with this version!
glob takes care of hidden files?
awesome solution :D
Instead of just } else { use } else if(!is_link($file)) { to be symlink safe
|
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);

1 Comment

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

Comments

10

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

1 Comment

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!
7

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

1 Comment

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

Comments

1

One way of doing it would be:

function unlinker($file)
{
    unlink($file);
}
$files = glob('*.*');
array_walk($files,'unlinker');
rmdir($dir);

Comments

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

Comments

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

1 Comment

you can't rmdir() a non empty directory, this is literally the reason for this thread

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.