0

私はPHPを使用しており、次のようなスクリプトを作成する必要があります。

2つのフォルダー構造を比較する必要があり、ソースフォルダーを参照して、参照ソースフォルダーに存在しない他の宛先フォルダーに存在するすべてのファイル/フォルダーを削除したいのですが、どうすればよいですか?

編集:

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

4 に答える 4

2

まず、両方のディレクトリの再帰的なリストが必要です。このような単純な関数が機能します。

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

私は物事をテストしました、そしてそれは今うまくいくはずです。もちろん、私の言葉を信じないでください。実際のデータを削除する前に、必ず独自の安全なテストを設定してください。

于 2010-05-08T06:38:34.303 に答える
0

私の仕事に貴重な時間を割いてくれてありがとう。私の問題に献身してくれたeriscoに特に感謝します。BelowCodeは、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);
}
于 2010-05-10T04:55:04.487 に答える
0

再帰ディレクトリについては、以下を使用してください。

$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にアクセスしてください。

于 2010-05-08T06:47:16.493 に答える
-1

最初に元のフォルダーの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);
     }
   }
}

これで問題が解決するはずです。それに応じて上記のコードを変更する必要があります(削除しようとしているフォルダーが空かどうかを確認するために上記のコードに再帰を含めます。空でない場合は、最初にすべてのファイル/フォルダーを削除する必要がありますその中に、親フォルダを削除します)。

于 2010-05-08T08:37:44.627 に答える