【问题标题】:Delete the unwanted files and folders from destination folder as compared to source folder与源文件夹相比,从目标文件夹中删除不需要的文件和文件夹
【发布时间】:2010-05-08 05:51:57
【问题描述】:

我正在使用 PHP,我需要编写如下脚本:

我要比较两个文件夹结构 并参考源文件夹 I 想要删除所有文件/文件夹 存在于其他目标文件夹中 参考源中不存在的 文件夹,我该怎么做?

已编辑:

$original = scan_dir_recursive('/var/www/html/copy2');
$mirror = scan_dir_recursive('/var/www/html/copy1');
function scan_dir_recursive($dir) {

  $all_paths = array();
  $new_paths = scandir($dir);

  foreach ($new_paths as $path) {
    if ($path == '.' || $path == '..') {
      continue;
    }
    $path = $dir . DIRECTORY_SEPARATOR . $path;
    if (is_dir($path)) {
      $all_paths = array_merge($all_paths, scan_dir_recursive($path));
    } else {
      $all_paths[] = $path;
    }
  }

  return $all_paths;

}
foreach($mirror as $mirr)
{
   if($mirr != '.' && $mirr != '..')
   {
     if(!in_array($mirr, $original))
     {
        unlink($mirr);
        // delete the file
     }

   }
}

上面的代码显示了我做了什么.. 在这里,我的 copy1 文件夹包含比 copy2 文件夹更多的文件,因此我需要删除这些额外的文件。

已编辑: 下面给出的输出是原始镜像的数组和两者的差异..

Original Array
(
    [0] => /var/www/html/copy2/Copy (5) of New Text Document.txt
    [1] => /var/www/html/copy2/Copy of New Text Document.txt
)

Mirror Array
(
    [0] => /var/www/html/copy1/Copy (2) of New Text Document.txt
    [1] => /var/www/html/copy1/Copy (3) of New Text Document.txt
    [2] => /var/www/html/copy1/Copy (5) of New Text Document.txt
)

Difference Array
(
    [0] => /var/www/html/copy1/Copy (2) of New Text Document.txt
    [1] => /var/www/html/copy1/Copy (3) of New Text Document.txt
    [2] => /var/www/html/copy1/Copy (5) of New Text Document.txt
)

当我迭代循环以删除差异数组时,必须根据显示的输出删除所有文件.. 我该如何纠正这个.. 删除循环如下所示。

$dirs_to_delete = array();
foreach ($diff_path as $path) {
    if (is_dir($path)) {
        $dirs_to_delete[] = $path;
    } else {
        unlink($path);
    }
}

while ($dir = array_pop($dirs_to_delete)) {
    rmdir($dir);
}

【问题讨论】:

  • 我试图解释我的评论中出了什么问题。昨晚我太累了,无法解决我一开始就知道会出错的事情,对不起!我的帖子现在更新了一个更好的答案。

标签: php recursion unlink


【解决方案1】:

首先,您需要两个目录的递归列表。像这样一个简单的函数就可以了:

function scan_dir_recursive($dir, $rel = null) {

  $all_paths = array();
  $new_paths = scandir($dir);

  foreach ($new_paths as $path) {

    if ($path == '.' || $path == '..') {
      continue;
    }

    if ($rel === null) {
        $path_with_rel = $path;
    } else {
        $path_with_rel = $rel . DIRECTORY_SEPARATOR . $path;
    }

    $full_path = $dir . DIRECTORY_SEPARATOR . $path;
    $all_paths[] = $path_with_rel;

    if (is_dir($full_path)) {
      $all_paths = array_merge(
        $all_paths, scan_dir_recursive($full_path, $path_with_rel)
      );
    }

  }

  return $all_paths;

}

然后你可以用array_diff计算它们的差异。

$diff_paths = array_diff(
    scan_dir_recursive('/foo/bar/mirror'),
    scan_dir_recursive('/qux/baz/source')
);

遍历此数组,您将能够开始删除文件。目录有点棘手,因为它们首先必须是空的。

// warning: test this code yourself before using on real data!

$dirs_to_delete = array();
foreach ($diff_paths as $path) {
    if (is_dir($path)) {
        $dirs_to_delete[] = $path;
    } else {
        unlink($path);
    }
}

while ($dir = array_pop($dirs_to_delete)) {
    rmdir($dir);
}

我已经测试了一些东西,现在应该可以正常工作了。当然,不要相信我的话。请务必在删除真实数据之前设置您自己的安全测试。

【讨论】:

  • 它不像我想要的那样工作,我只想从镜像文件夹中删除那些不在源文件夹中的文件,但是代码会从镜像文件夹中删除所有文件......请帮助
  • 这可能是因为您的镜像位于/foo/bar/mirror,而您的源位于/baz/qux/sourcearray_diff 当然会认为一切都不同。要么切掉这些路径部分,要么在scan_dir_recursive 中构建功能以首先排除它们。
  • 我已将scan_dir_recursive 更改为更像scandir,而不是将初始目录推送到每个路径上。现在您应该可以更轻松地使用array_diff
  • 非常感谢 Erisco 为我的工作付出了宝贵的努力,但为了使其正常工作,我只添加了一行来取消链接文件和文件夹。请在下面的更改中查看我的回复代码被注释为“添加代码以取消链接”
【解决方案2】:

对于递归目录,请使用:

$modified_directory = new RecursiveIteratorIterator(
       new RecursiveDirectoryIterator('path/to/modified'), true
);
$modified_files = array();
foreach ($modified_directory as $file)
{
    $modified_files []= $file->getPathname();
}

您可以执行其他操作,例如 $file->isDot() 或 $file->isFile()。有关 SPLFileInfo 的更多文件命令,请访问http://www.php.net/manual/en/class.splfileinfo.php

【讨论】:

【解决方案3】:

感谢大家为我的工作付出的宝贵时间,特别感谢 erisco 对我的问题的奉献,Below Code 是完成我应该做的任务的完美代码,在 erisco 的最后编辑中略有变化回复...

$source = '/var/www/html/copy1';
$mirror = '/var/www/html/copy2';

function scan_dir_recursive($dir, $rel = null) {

  $all_paths = array();
  $new_paths = scandir($dir);

  foreach ($new_paths as $path) {

    if ($path == '.' || $path == '..') {
      continue;
    }

    if ($rel === null) {
        $path_with_rel = $path;
    } else {
        $path_with_rel = $rel . DIRECTORY_SEPARATOR . $path;
    }

    $full_path = $dir . DIRECTORY_SEPARATOR . $path;
    $all_paths[] = $path_with_rel;

    if (is_dir($full_path)) {
      $all_paths = array_merge(
        $all_paths, scan_dir_recursive($full_path, $path_with_rel)
      );
    }

  }

  return $all_paths;

}
$diff_paths = array_diff(
    scan_dir_recursive($mirror),
    scan_dir_recursive($source)
);



echo "<pre>Difference ";print_r($diff_paths);

$dirs_to_delete = array();
foreach ($diff_paths as $path) {
    $path = $mirror."/".$path;//added code to unlink.
    if (is_dir($path)) {

        $dirs_to_delete[] = $path;
    } else {

        if(unlink($path))
        {
            echo "File ".$path. "Deleted.";
        }
    }
}

while ($dir = array_pop($dirs_to_delete)) {
    rmdir($dir);
}

【讨论】:

    【解决方案4】:

    首先对原始文件夹执行 scandir(),
    然后对镜像文件夹执行 scandir。
    开始遍历镜像文件夹数组并检查该文件是否存在于原始文件夹的 scandir() 中。像这样的

    $original = scandir('path/to/original/folder'); $mirror = scandir('path/to/mirror/folder'); foreach($mirror as $mirr) { if($mirr != '.' && $mirr != '..') { if(in_array($mirr, $original)) { // do not delete the file } else { // delete the file unlink($mirr); } } }

    这应该可以解决您的问题。您需要相应地修改上面的代码(在上面的代码中包含一些递归来检查您要删除的文件夹是否为空,如果它不为空,那么您首先需要删除所有文件/文件夹然后删除父文件夹)。

    【讨论】:

    • 简单地复制和粘贴代码并不能完全帮助我亲爱的朋友。先把你自己的代码贴在这里,然后只有一个人才能正确理解你实际上在做什么。
    • Yaar gaurav 我从早上开始就在尝试这样做,你的代码正在做与“erisco”相同的事情它删除了我所有的文件,我只需要从镜像文件夹中删除那些文件源文件夹中不存在
    • 好的,我知道当代码不能相应地工作时会很烦人。获取原始数组和镜像数组的 print_r() ,然后查看它们是否有任何共同元素的输出。我只能建议在我的水平最好的兄弟。你一定在这里做了一些不同的逻辑。试着休息一下,然后重新思考你的逻辑。我将自己编写此问题的代码,然后在此处发布此帖子的答案。 :-)
    • 谢谢伙计..我会这样做并等待你的回复......请再次恢复......
    • 请查看更新后的问题我已经显示了 print_r() 输出和它们的 array_diff print_r 输出..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多