【问题标题】:rmdir no such file directory error although directory existrmdir no such file directory 错误虽然目录存在
【发布时间】:2014-06-10 14:49:23
【问题描述】:

如果使用此功能删除一个目录+里面的所有文件。

function delete_files($target)
{
    if(is_dir($target))
    {
        $files = glob($target . '*', GLOB_MARK);
        foreach($files as $file)
        {
            delete_files($file);
        }
        rmdir($target);
    }
    elseif(is_file($target))
    {
        unlink($target);
    }
}
delete_files($directory);

但是每当我这样做时,我都会收到以下错误消息:

警告:rmdir(directory/12) [function.rmdir]: 没有这样的文件或目录 在 delete_files.php 中

"directory/12" 是我要删除的目录的正确名称。我不明白为什么它说它不存在,因为它确实存在!奇怪的是,即使我收到错误消息,目录 DID 也被删除了。

所以我在 for 循环之前添加了一行代码 print_n($files);,它让我使用了两个数组——一个包含目录(“directory/12”),另一个包含目录的所有文件(“directory /12/01.gif”、“目录/12/02.gif”等)。所以我认为该目录必须在 for 循环中被删除并删除了 rmdir($target) 行并再次尝试。这一次,目录中的所有文件都被删除了,但目录本身仍然存在。

显然,rmdir 确实正确删除了目录。但是,为什么它会事先给我它不存在的错误消息?

【问题讨论】:

  • 使用目录名(__ FILE __);你在函数中也缺少一个 }
  • 你确定php进程有删除文件的权限吗?这是在 linux 服务器上运行的吗?

标签: php rmdir


【解决方案1】:

如果您在目录名称后附加一个斜杠,它将起作用。

说明:当您最初以delete_files("directory/12") 调用该函数时,传递给glob() 调用的参数将如下所示:

$files = glob("directory/12*", GLOB_MARK);

假设您在directory/ 中没有其他名称以12 开头的文件,则只会返回"directory/12/"(由于GLOB_MARK 而附加了一个斜线)。然后该函数将使用该参数递归调用自身,从而导致顶级目录被处理两次。

当然,如果您确实碰巧有一些其他文件或目录名为directory/123,那么它也会被删除,这可能不是你想要什么。


要正确解决此问题,您应该确保您的函数可以正确处理目录,即使它们在没有尾部斜杠的情况下传入也是如此。最简单的方法是始终将斜杠附加到目录名称​​之前 通配它们,如下所示:

$files = glob($target . '/*');

但是,请注意,如果您的目录碰巧包含一些与* 不匹配的文件,例如dotfiles,这仍然可能失败(尽管破坏性较小),因为它们不会被删除,从而导致随后的rmdir()失败,因为目录不会为空。

更强大的解决方案是使用scandir() 而不是glob(),如下所示:

$files = array_diff( scandir($target), array('.', '..') );
foreach ($files as $file) {
    delete_files("$target/$file");
}

(需要array_diff() 来消除特殊的. 和.. 目录条目,如果不排除它们会导致代码永远递归。)

剩下的一个潜在故障模式是,此代码将愉快地跟随符号链接到目录并尝试删除它们指向的目录中的所有内容(然后无法删除链接本身,因为rmdir() 无法删除符号链接)。要解决此问题,您可能需要将 is_dir($target) 测试替换为 !is_link($target) && is_dir($target)。


全部放在一起,生成的代码如下所示:

function delete_files($target)
{
    if(!is_link($target) && is_dir($target))
    {
        // it's a directory; recursively delete everything in it
        $files = array_diff( scandir($target), array('.', '..') );
        foreach($files as $file) {
            delete_files("$target/$file");
        }
        rmdir($target);
    }
    else
    {
        // probably a normal file or a symlink; either way, just unlink() it
        unlink($target);
    }
}
delete_files($directory);

附言。另见How do I recursively delete a directory and its entire contents (files + sub dirs) in PHP?

【讨论】:

    【解决方案2】:

    因为您在第一次工作时调用它两次,第二次出现错误。

    我无法证明这一点,但使用这样的递归代码就是问题所在。

    【讨论】:

      猜你喜欢
      • 2016-11-01
      • 2020-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 2018-09-30
      • 2019-03-25
      • 2014-11-09
      相关资源
      最近更新 更多