4

我有这个代码来递归删除文件和目录。它工作正常,但有一个小问题。如果 $path = /var/www/foo/ 它将删除 foo 中的所有内容,但不会删除 foo。我也想删除 foo 目录。任何想法?

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

4 回答 4

12

为什么还要在你的函数中递归?

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

它有效,因为RII::CHILD_FIRST在父元素之前迭代子元素。所以当它到达目录时,它应该是空的。

但实际错误是由于您删除目录的位置。在内部目录中,您在父迭代中执行此操作。这意味着您的根目录将永远不会被删除。我建议在本地删除迭代中这样做:

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

注意这两个变化。我们只删除迭代内的空目录。调用$this->delete()它将为您处理删除。第二个变化是在rmdir方法末尾添加了final ...

于 2010-12-20T14:51:35.330 回答
3

你错过了最后一个rmdir。您可以$this->delete($path)像这样调用它:

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

或者您可以像这样更改foreach-loop:

public function delete($path) {
    //snip

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

    rmdir($path);
}

另外,我当然希望您验证您到达那里的路径,如果这对用户可见(例如“删除我的 Webspace 上的所有内容”-功能。我的意思是,如果有人/etc/进入那里,您将获得很多乐趣。

于 2010-12-20T14:49:20.727 回答
0

尝试这个

未设置($directoryIterator);rmdir($filePath);

于 2013-07-01T10:42:06.137 回答
-1
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);
}

?

于 2010-12-20T14:50:31.897 回答