tags:

views:

56

answers:

2

Hello all,

I would like to extract a zip folder to a location and to replace all files and folders except a few, how can I do this?

I currently do the following.

$backup = realpath('./backup/backup.zip');

$zip = new ZipArchive();

if ($zip->open("$backup", ZIPARCHIVE::OVERWRITE) !== TRUE) {

    die ('Could not open archive');

}

$zip->extractTo('minus/');

$zip->close();

How can I put conditions in for what files and folders should NOT be replaced? It would be great if some sort of loop could be used.

Thanks all for any help

+2  A: 

You could do something like this, I tested it and it works for me:

// make a list of all the files in the archive
$entries = array();
for ($idx = 0; $idx < $zip->numFiles; $idx++) {
    $entries[] = $zip->getNameIndex($idx);
}

// remove $entries for the files you don't want to overwrite

// only extract the remaining $entries
$zip->extractTo('minus/', $entries);

This solution is based on the numFiles property and the getNameIndex method, and it works even when the archive is structured into subfolders (the entries will look like /folder/subfolder/file.ext). Also, the extractTo method takes a second optional paramer that holds the list of files to be extracted.

Victor Stanciu
Damn you Victor! You beat me to the punch :). +1 for a clean solution.
Andre Artus
@Victor: It has been a number of years since I did PHP, is it necessary to check "if ($zip->numFiles > 0)"?
Andre Artus
@Andre: actually, not really, no, it's just a habit of mine to check before assuming something. I shortened the code a little bit.
Victor Stanciu
@Victor - that worked perfectly! I just needed to exclude 10 files out of 300 so I just removed elements from the array I did not need. Thank you! :)
Abs
@Victor: I get where you are coming from.
Andre Artus
A: 

If you just want to extract specific files from the archive (and you know what they are) then use the second parameter (entries).

 $zip->extractTo('minus/', array('file1.ext', 'newfile2.xml'));

If you want to extract all the files that do not exist, then do you can try one of the following:

$files = array();

for($i = 0; $i < $zip->numFiles; $i++) {
    $filename = $zip->getNameIndex($i);
    // if $filename not in destination / or whatever the logic is then
        $files[] = $filename;
}
$zip->extractTo($path, $files);      
$zip->close();

You can also use $zip->getStream( $filename ) to read a stream that you then write to the destination file.

Andre Artus