Mihir
Mihir

Reputation: 348

How to check if a folder of specific name exists in zip file or not?

I have a zip file that will be open using php ziparchive function and later I need to check if a folder exists inside the zip?

For example, I have a file ABC.zip. Check if there is a sub-folder xyz in folder pqr inside zip file, so if extracted it would be ABC/pqr/xyz.

Upvotes: 0

Views: 4798

Answers (2)

Victor
Victor

Reputation: 815

You can use ZipArchive::locateName() method in most cases. So simple solution would be

$zip = new \ZipArchive();
$zip->open('ABC.zip');
if($zip->locateName('/pqr/xyz/') !== false) {
    // directory exists
}

But some archives may not have directories listed in index even though they have all files with right internal paths. In this case locateName will return false for directory.

Here is a snippet to fix it. You can extend \ZipArchive or use it in your own way.

class MyZipArchive extends \ZipArchive
{
    /**
     * Locates first file that contains given directory
     *
     * @param $directory
     * @return false|int
     */
    public function locateDir($directory)
    {
            // Make sure that dir name ends with slash
            $directory = rtrim($directory, '/') . '/';
            return $this->locateSubPath($directory);
    }

    /**
     * @param $subPath
     * @return false|int
     */
    public function locateSubPath($subPath)
    {
        $index = $this->locateName($subPath);
        if ($index === false) {
            // No full path found
            for ($i = 0; $i < $this->numFiles; $i++) {
                $filename = $this->getNameIndex($i);
                if ($this->_strStartsWith($filename, $subPath)) {
                    return $i;
                }
            }
        }
        return $index;
    }

    /**
     * Can be replaced with str_starts_with() in PHP 8
     *
     * @param $haystack
     * @param $needle
     * @return bool
     */
    protected function _strStartsWith($haystack, $needle)
    {
        if (strlen($needle) > strlen($haystack)) {
            return false;
        }
        return strpos($haystack, $needle) === 0;
    }
}

Then

$zip = new MyZipArchive();
$zip->open('ABC.zip');
if($zip->locateDir('/pqr/xyz/') !== false) {
    // directory exists
}

Upvotes: 2

Ahmad ghoneim
Ahmad ghoneim

Reputation: 927

i did some researching and that's what i came up with it's working very well and i added comments to make it easy to understand

<?php
$zip = new ZipArchive;
$dir = __DIR__ . '/test'; // directory name
$zipFileName = __DIR__ . '/ahmad.zip'; // zip name
$fileName ='ahmad.php'; //file name

// unzip the archive to directory
$res = $zip->open($zipFileName);
if ($res === TRUE) {
    $zip->extractTo($dir);
    $zip->close();
} else {
    echo 'failed, code:' . $res;
}

// search for the file in the directory
$array = (scandir($dir));
if (in_array($fileName, $array)) {
    echo "File exists";
}
else {
    echo "file doesn't exist";
}

// Delete the directory after the search is done
$it = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($it,
             RecursiveIteratorIterator::CHILD_FIRST);
foreach($files as $file) {
    if ($file->isDir()){
        rmdir($file->getRealPath());
    } else {
        unlink($file->getRealPath());
    }
}
rmdir($dir);

?>

or you can go for

<?php
$z = new ZipArchive();
if($z->open('test.zip') === TRUE )
{
    if ($z->locateName('test.php') !== false)
    {
    echo "file exists";
    }else {
        echo "file doesn't exist";
    }
}
else {
    echo 'failed to open zip archive';
}

?>

which is a lot easier a user posted it as an answer then deleted it so i added it too

Upvotes: 0

Related Questions