Search code examples
phprecursionunlink

Delete the unwanted files and folders from destination folder as compared to source folder


I am using PHP and I need to script something like below:

I have to compare two folder structure and with reference of source folder I want to delete all the files/folders present in other destination folder which do not exist in reference source folder, how could i do this?

EDITED:

$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
     }

   }
}

The above code shows what i did.. Here My copy1 folder contains extra files than copy2 folders hence i need these extra files to be deleted.

EDITED: Below given output is are arrays of original Mirror and of difference of both..

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
)

when i iterate a loop to delete on difference array all files has to be deleted as per displayed output.. how can i rectify this.. the loop for deletion is given below.

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

Solution

  • First you need a recursive listing of both directories. A simple function like this will work:

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

    Then you can compute their difference with array_diff.

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

    Iterating over this array, you will be able to start deleting files. Directories are a bit trickier because they must be empty first.

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

    I've tested things and it should be working well now. Of course, don't take my word for it. Make sure to setup your own safe test before deleting real data.