PharData extractTo方法抛出异常并返回消息“”;路径已经存在”;


PharData extractTo method throws exception with message "path already exists"

我正在使用PHP的PharData类从tar档案中提取文件,但我看到了一个非常奇怪的行为。这是我正在使用的代码:

$filePattern = "$homeDirectory/*tgz";
$fileArray = glob($filePattern);
$i = 0;
foreach($fileArray as $file) {
  $phar = new PharData($file);
  $phar->extractTo($homeDirectory."/logs-$i");
  array_push($extractedDirectories, $homeDirectory."/logs-$i");
  $i++;
}

foreach循环应该提取主目录中的每个存档,并将它们移动到名为"logs-n"的目录中,其中n是主目录下的整数,包括0。然而,我得到了一个例外:

 Encountered error: exception 'PharException' with message 'Extraction from phar "/home/user/file.tgz" failed: Cannot extract "output" to "/home/user/logs-0/output", path already exists'

我的第一个想法是存档包含两个"输出"目录,所以我手动提取了存档并检查了内容;瞧,只有一个输出目录。我想到的另一个想法是,循环可能试图对同一个存档运行两次,但在这两种情况下都没有发生。

重申目录"logs-n"不存在,直到循环开始处理特定的tar存档。然后它抛出一个异常,表示提取它的路径已经存在。

我开始认为我在PharData类或extractTo方法中遇到了某种限制,但php.net上的文档都没有涉及到这样的内容,我在SO上也没有发现任何涉及到这样内容的问题,这就是我添加这个的原因。

好吧,所以在我的头撞了一下之后。问题是我没有使用extractTo方法的全套参数。该方法接受一个必需参数和两个可选参数,第一个可选参数是包含要提取的特定文件名的字符串或数组,第二个可选参数为"覆盖"标志。当我将代码更改为以下内容时:

foreach($fileArray as $file) {
  $phar = new PharData($file);
  $phar->extractTo($homeDirectory."/logs-$i", null, true);
  array_push($extractedDirectories, $homeDirectory."/logs-$i");
  $i++;
}

在这里,我只是要求提取所有文件,并允许覆盖。一旦我这样做,问题就解决了。如果你阅读了这个方法的PHP文档,它会说这个标志决定是否覆盖现有的文件。我真的不知道为什么这对工作来说是必要的。我能想到的最接近的原因是,由于某种原因,extractTo方法在第一次迭代子日志文件后看到父"输出"目录已经存在,但失败了。