5

I have compressed_file.zip on a site with this structure:

zip file

I want to extract all content from version_1.x folder to my root folder:

desired

How can I do that? is possible without recursion?

quantme
  • 3,609
  • 4
  • 34
  • 49

3 Answers3

7

It's possible, but you have to read and write the file yourself using ZipArchive::getStream:

$source = 'version_1.x';
$target = '/path/to/target';

$zip = new ZipArchive;
$zip->open('myzip.zip');
for($i=0; $i<$zip->numFiles; $i++) {
    $name = $zip->getNameIndex($i);

    // Skip files not in $source
    if (strpos($name, "{$source}/") !== 0) continue;

    // Determine output filename (removing the $source prefix)
    $file = $target.'/'.substr($name, strlen($source)+1);

    // Create the directories if necessary
    $dir = dirname($file);
    if (!is_dir($dir)) mkdir($dir, 0777, true);

    // Read from Zip and write to disk
    $fpr = $zip->getStream($name);
    $fpw = fopen($file, 'w');
    while ($data = fread($fpr, 1024)) {
        fwrite($fpw, $data);
    }
    fclose($fpr);
    fclose($fpw);
}
netcoder
  • 66,435
  • 19
  • 125
  • 142
  • It looks that will work but returns these errors: `Warning: fopen(//) [function.fopen]: failed to open stream: Is a directory in /extract_zip.php on line 21 Warning: fclose(): supplied argument is not a valid stream resource in /extract_zip.php on line 26 Warning: fopen(//application/) [function.fopen]: failed to open stream: Is a directory in /extract_zip.php on line 21 Warning: mkdir() [function.mkdir]: No such file or directory in /extract_zip.php on line 17` There are hundreds of lines like above; file has 200+ items – quantme Nov 12 '11 at 18:04
  • @quantme: The above code works fine for me. You probably forgot something. You may want to ask another question for this other issue. – netcoder Nov 12 '11 at 18:40
  • This code works very well for me. I had the same question as quantme. The only thing missing I think is a $zip->close and a if ($zip->open('myzip.zip') === TRUE) { Too bad I cannot mark this question as answered by you. – Kim Stacks Mar 14 '12 at 02:09
  • I have modified your answer a tad by adding the parts that I think are necessary and I improved the skip files portion because your code may write out the version 1.1_x folder as well. – Kim Stacks Mar 14 '12 at 02:19
1

I was getting similar errors to @quantme when using @netcoder's solution. I made a change to that solution and it works without any errors.

$source = 'version_1.x';
$target = '/path/to/target';

$zip = new ZipArchive;
if($zip->open('myzip.zip') === TRUE) {
    for($i = 0; $i < $zip->numFiles; $i++) {
        $name = $zip->getNameIndex($i);

        // Skip files not in $source
        if (strpos($name, "{$source}/") !== 0) continue;

        // Determine output filename (removing the $source prefix)
        $file = $target.'/'.substr($name, strlen($source)+1);

        // Create the directories if necessary
        $dir = dirname($file);
        if (!is_dir($dir)) mkdir($dir, 0777, true);

        // Read from Zip and write to disk
        if($dir != $target) {
            $fpr = $zip->getStream($name);
            $fpw = fopen($file, 'w');
            while ($data = fread($fpr, 1024)) {
                fwrite($fpw, $data);
            }
            fclose($fpr);
            fclose($fpw);
        }
    }
    $zip->close();
}
Gary
  • 318
  • 3
  • 14
0

Look at the docs for extractTo. Example 1.

John Watson
  • 2,554
  • 1
  • 17
  • 13
  • 1
    This is not a good answer because extractTo in all sorts of ways, would always extract the version 1.1_x folder no matter what. I have tried this many times and only ZipArchive::getStream as suggested by @netcoder works. – Kim Stacks Mar 14 '12 at 02:11