Php 为什么在Windows中,两次尝试删除文件都有效?

Php 为什么在Windows中,两次尝试删除文件都有效?,php,windows,git,permission-denied,phing,Php,Windows,Git,Permission Denied,Phing,我一直在努力用PHP为我开发的Windows机器编写一个持续集成脚本 克隆了一个Git存储库后,我无法制作一个脚本将其全部删除。(包括.git文件夹和其中的所有内容)。我收到了“拒绝许可”错误 这似乎是断断续续的。我尝试了Phing,但失败了,但却导致了我的失败,所以我并不孤单——但使用attrib的解决方案对我不起作用 我终于意识到,只需两次尝试就可以删除其中的一些文件夹和/或文件。我的PHP代码最终成功了,是这样的: <?php function delTree($dir, $igno

我一直在努力用PHP为我开发的Windows机器编写一个持续集成脚本

克隆了一个Git存储库后,我无法制作一个脚本将其全部删除。(包括.git文件夹和其中的所有内容)。我收到了“拒绝许可”错误

这似乎是断断续续的。我尝试了Phing,但失败了,但却导致了我的失败,所以我并不孤单——但使用
attrib
的解决方案对我不起作用

我终于意识到,只需两次尝试就可以删除其中的一些文件夹和/或文件。我的PHP代码最终成功了,是这样的:

<?php
function delTree($dir, $ignore = array()) {

    // no need to continue if $dir doesn't exist
    if (!file_exists($dir))
        return true;

    // must not continue if it's a link. trigger an error.
    if (is_link($dir)) {
        trigger_error("Cannot delete $dir: it's a link.", E_ERROR);
        return false;
    }

    // if it's a file, delete it and return.
    if (is_file($dir)) {
        return tryUnlink($dir, 2);
    }

    // it's a directory. so...
    // build an array of files/directories within it to delete
    $files = array_diff(
            scandir($dir), array('.', '..'), $ignore
    );

    // delete each directory within $dir
    foreach ($files as $file) {
        delTree("$dir/$file", $ignore);
    }

    // delete $dir itself
    return tryRmdir($dir, 2);
}
function tryUnlink($file, $attempts = 2){
    $result = unlink($file);
    if (!$result) {
        if ($attempts > 1){
            return tryUnlink($file, $attempts--);
        } else {
            trigger_error("Cannot delete file $file", E_ERROR);
            return false;
        }
    }
    return true;
}

function tryRmdir($dir, $attempts = 2){
    $result = rmdir($dir);
    if (!$result) {
        if ($attempts > 1){
            return tryRmdir($dir, $attempts--);
        } else {
            trigger_error("Cannot delete directory $dir", E_ERROR);
            return false;
        }
    }
    return true;
}
可能还有另外10个埋在我的回购协议中


原因可能是什么?

两个函数
tryUnlink()
tryRmdir()
都会导致无限循环(除非它被实际删除)。查看以下代码段+输出

代码:

鉴于并没有说删除会在第二次运行时启动。

从Windows 7(或者Vista?)开始,第一次尝试删除目录树失败的情况很少见,但并非异常。我认为这是由于文件系统异步处理删除操作而产生的竞争条件造成的


正如您已经发现的,您可以通过重试操作来解决此问题;就我个人而言,我从未见过它连续失败两次,尽管为了安全起见,我通常允许它重试三四次。

你甚至可以
取消目录的链接()
吗?本以为它只用于文件。别忘了,如果任何进程正在使用某个目录中/下的任何内容,则不能删除该目录。@MarcB,但为什么每次都要尝试删除一个空目录或一行两次文件,而不会失败呢?如果给定的路径是一个文件,那么只有一次会失败吗?你从delTree返回…@Jodes:因为你不会只尝试两次。您正在执行
$attempts--
,这意味着每次$attempts(
2
)的原始值都会传递到tryUnlink()和tryRmdir()。这意味着这是一个无限递归循环,你只需不断尝试,直到它最终删除。啊,我明白了,你是对的,前缀/后缀起作用-最好让这成为对原始问题的一个好答案,我将删除上面讨论的我的部分。确切地说,$x首先执行减法,然后将结果作为参数向下传递
$x--
传递原始值,然后进行减法运算,将减法后的值保留在无限递归调用堆栈的顶部。如果递归调用曾经返回过,那么在某个时刻,您会得到
尝试=1
。很有趣,谢谢-您有关于这方面的更多信息吗?没有,只是我自己的经验。据我记忆所及,在XP中没有发生。请注意,如果您经常看到这种情况(比说,十分之一的时间)可能有一个特定的原因,例如,防病毒软件。
rm -r .git -Force
rmdir .git /s /q
<?php

function foo ($attempts = 2) {
   echo "attempts = $attempts\n";
   if ($attempts > 1) {
      foo ($attempts--);
   } else {
      echo "returning with \$attempts <= 1\n";
  }
}
foo(2);
attempts = 2
attempts = 2
attempts = 2
[...many many many dupes...]
attempts = 2
attempts = 2
attempts = 2
Segmentation fault (core dumped)