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

StackOverflow https://stackoverflow.com/questions/2793090

  •  04-10-2019
  •  | 
  •  

Question

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);
}
Was it helpful?

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.

OTHER TIPS

For recursive directories please use:

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

You can do other things like $file->isDot(), or $file->isFile(). For more file commands with SPLFileInfo visit http://www.php.net/manual/en/class.splfileinfo.php

Thanks all for the precious time given to my work, Special Thanks to erisco for his dedication for my problem, Below Code is the perfect code to acomplish the task I was supposed to do, with a little change in the erisco's last edited reply...

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

First do a scandir() of the original folder,
then do a scandir on mirror folder.
start traversing the mirror folder array and check if that file is present in the scandir() of original folder. something like this


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

this should solve your problem. you will need to modify the above code accordingly (include some recursion in the above code to check if the folder that you are trying to delete is empty or not, if it is not empty then you will first need to delete all the file/folders in it and then delete the parent folder).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top