5

I wrote recursive PHP function for folder deletion. I wonder, how do I modify this function to delete all files and folders in webhosting, excluding given array of files and folder names (for ex. cgi-bin, .htaccess)?

BTW

to use this function to totally remove a directory calling like this

recursive_remove_directory('path/to/directory/to/delete');

to use this function to empty a directory calling like this:

recursive_remove_directory('path/to/full_directory',TRUE);

Now the function is

function recursive_remove_directory($directory, $empty=FALSE)
{
    // if the path has a slash at the end we remove it here
    if(substr($directory,-1) == '/')
    {
        $directory = substr($directory,0,-1);
    }

    // if the path is not valid or is not a directory ...
    if(!file_exists($directory) || !is_dir($directory))
    {
        // ... we return false and exit the function
        return FALSE;

    // ... if the path is not readable
    }elseif(!is_readable($directory))
    {
        // ... we return false and exit the function
        return FALSE;

    // ... else if the path is readable
    }else{

        // we open the directory
        $handle = opendir($directory);

        // and scan through the items inside
        while (FALSE !== ($item = readdir($handle)))
        {
            // if the filepointer is not the current directory
            // or the parent directory
            if($item != '.' && $item != '..')
            {
                // we build the new path to delete
                $path = $directory.'/'.$item;

                // if the new path is a directory
                if(is_dir($path)) 
                {
                    // we call this function with the new path
                    recursive_remove_directory($path);

                // if the new path is a file
                }else{
                    // we remove the file
                    unlink($path);
                }
            }
        }
        // close the directory
        closedir($handle);

        // if the option to empty is not set to true
        if($empty == FALSE)
        {
            // try to delete the now empty directory
            if(!rmdir($directory))
            {
                // return false if not possible
                return FALSE;
            }
        }
        // return success
        return TRUE;
    }
}
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
heron
  • 3,611
  • 25
  • 80
  • 148
  • See http://trac.symfony-project.org/browser/branches/1.4/lib/util/sfToolkit.class.php#L54 for an existing implementation. –  Oct 07 '11 at 13:51

3 Answers3

5

Try something like this:

$it = new RecursiveIteratorIterator(
  new RecursiveDirectoryIterator('%yourBaseDir%'),
  RecursiveIteratorIterator::CHILD_FIRST
);

$excludeDirsNames = array();
$excludeFileNames = array('.htaccess');

foreach($it as $entry) {
  if ($entry->isDir()) {
    if (!in_array($entry->getBasename(), $excludeDirsNames)) {
      try {
        rmdir($entry->getPathname());
      }
      catch (Exception $ex) {
        // dir not empty
      }
    }
  }
  elseif (!in_array($entry->getFileName(), $excludeFileNames)) {
    unlink($entry->getPathname());
  }
}
Yoshi
  • 54,081
  • 14
  • 89
  • 103
  • My base directory is www folder and the file with this function will be inside www folder.What will be `%yourBaseDir%`? it will do whole recursive folder deletion too?? and how to deal with .htaccess? – heron Oct 07 '11 at 09:16
  • My base directory is www folder and the file with this function will be inside www folder.What will be %yourBaseDir%? I mean the function must delete all files and folders in current folder and exclude arrays, and itself – heron Oct 07 '11 at 09:22
  • Getting errors: `Directory not empty on line rmdir($entry->getPathname());' – heron Oct 07 '11 at 09:32
  • still having issue: Directory not empty – heron Oct 07 '11 at 09:39
  • someone gave me idea: if (substr($oneExcludedFileOrDirectory, 0, strlen($currentDir) === $currentDir) { echo "Directory not empty"; } but i dunno where it should be – heron Oct 07 '11 at 10:18
  • same issue on line rmdir($entry->getPathname()); – heron Oct 07 '11 at 10:31
  • Take a look at this scrshot http://prntscr.com/3dbn0 In common folder located .htaccess file. it can't delete .htaccess – heron Oct 07 '11 at 10:33
  • changed again, brute force this time ;) – Yoshi Oct 07 '11 at 10:37
  • Mate, the function must not delete .htaccess - first one, which located in the root folder (but it must delete all other ones), as you see i have second one in common folder – heron Oct 07 '11 at 10:40
  • Then do some path checking on the file names. The code I posted is no far from magic. Have a look here [SplFileInfo](http://www.php.net/manual/de/class.splfileinfo.php) for reference. – Yoshi Oct 07 '11 at 10:43
  • Warning: unlink(./cgi-bin) [function.unlink]: Is a directory in /home/heimann/public_html/update.php on unlink($entry->getPathname()); – heron Oct 07 '11 at 11:20
0
  1. You could provide an extra array parameter $exclusions to recursive_remove_directory(), but you'll have to pass this parameter every time recursively.

  2. Make $exclusions global. This way it can be accessed in every level of recursion.

George Brighton
  • 5,131
  • 9
  • 27
  • 36
jan
  • 2,879
  • 2
  • 19
  • 28
0

I'm using this function to delete the folder with all files and subfolders:

function removedir($dir) {
    if (substr($dir, strlen($dir) - 1, 1) != '/')
        $dir .= '/';
    if ($handle = opendir($dir)) {
        while ($obj = readdir($handle)) {
            if ($obj != '.' && $obj != '..') {
                if (is_dir($dir . $obj)) {
                    if (!removedir($dir . $obj))
                        return false;
                }
                else if (is_file($dir . $obj)) {
                    if (!unlink($dir . $obj))
                        return false;
                }
            }
        }
        closedir($handle);
        if (!@rmdir($dir))
            return false;
        return true;
    }
    return false;
}

$folder_to_delete = "folder"; // folder to be deleted

echo removedir($folder_to_delete) ? 'done' : 'not done';

Iirc I got this from php.net

George Brighton
  • 5,131
  • 9
  • 27
  • 36
Arda
  • 6,756
  • 3
  • 47
  • 67