Recursive delete

I have this code for recursively deleting files and directories. It works great, but has a slight problem. If $ path = / var / www / foo / it will delete everything inside foo, but not foo. I want to also remove the foo directory. Any ideas?

public function delete($path) { if(!file_exists($path)) { throw new RecursiveDirectoryException('Directory doesn\'t exist.'); } $directoryIterator = new DirectoryIterator($path); foreach($directoryIterator as $fileInfo) { $filePath = $fileInfo->getPathname(); if(!$fileInfo->isDot()) { if($fileInfo->isFile()) { unlink($filePath); } else if($fileInfo->isDir()) { if($this->emptyDirectory($filePath)) { rmdir($filePath); } else { $this->delete($filePath); rmdir($filePath); } } } } } 
+4
source share
4 answers

Why is even recursion in your function?

 public function delete($path) { $it = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::CHILD_FIRST ); foreach ($it as $file) { if (in_array($file->getBasename(), array('.', '..'))) { continue; } elseif ($file->isDir()) { rmdir($file->getPathname()); } elseif ($file->isFile() || $file->isLink()) { unlink($file->getPathname()); } } rmdir($path); } 

It works because RII::CHILD_FIRST over the children before the parent. Thus, by the time it reaches the directory, it should be empty.

But the actual error is related to where you delete your directories. In internal directories, you do this in the parent iteration. This means that your root directory will never be deleted. I suggest doing this in a local delete iteration:

 public function delete($path) { if(!file_exists($path)) { throw new RecursiveDirectoryException('Directory doesn\'t exist.'); } $directoryIterator = new DirectoryIterator($path); foreach($directoryIterator as $fileInfo) { $filePath = $fileInfo->getPathname(); if(!$fileInfo->isDot()) { if($fileInfo->isFile()) { unlink($filePath); } elseif($fileInfo->isDir()) { if($this->emptyDirectory($filePath)) { rmdir($filePath); } else { $this->delete($filePath); } } } } rmdir($path); } 

Notice the two changes. We remove only empty directories within the iteration. Calling $this->delete() on it will handle the deletion for you. The second change is adding the final rmdir at the end of the method ...

+12
source

You are missing the last rmdir . You can call it after $this->delete($path) as follows:

 $this->delete($path); rmdir($path); 

Or you can change foreach -loop as follows:

 public function delete($path) { //snip foreach($directoryIterator as $fileInfo) { //snip else { $this->delete($filePath); } } } } rmdir($path); } 

In addition, I hope that you confirm which paths you will get there if it is visible to the user (for example, "Delete everything in my web space"). I mean, you will have a lot of fun if someone goes through /etc/ .

+3
source

try it

unset ($ directoryIterator); RmDir ($ Filepath);

0
source
 function delete($path){ if(!file_exists($path)) { throw new RecursiveDirectoryException('Directory doesn\'t exist.'); } $directoryIterator = new DirectoryIterator($path); foreach($directoryIterator as $fileInfo) { $filePath = $fileInfo->getPathname(); if(!$fileInfo->isDot()) { if($fileInfo->isFile()) { unlink($filePath); } else if($fileInfo->isDir()) { if($this->emptyDirectory($filePath)) { rmdir($filePath); } else { $this->delete($filePath); rmdir($filePath); } } } } rmdir($path); } 

?

-1
source

Source: https://habr.com/ru/post/1332773/


All Articles