You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用PHP压缩整个文件夹并排除指定子目录?

Fixing Directory Exclusion in Your PHP ZIP Compression Code

Hey there, let's get that exclusion logic working for you. The issue with your current approach is that you weren't properly checking if each file belongs to the directories you want to skip. Here are two solid solutions to exclude upload/data b and upload/data c from your ZIP archive:

Solution 1: Add Exclusion Check in the Foreach Loop

This is a straightforward tweak to your existing code. We'll define the paths we want to exclude, then check each file's relative path against this list before adding it to the ZIP.

// Get real path for our folder
$rootPath = realpath('folder-to-zip');
// Initialize archive object
$zip = new ZipArchive();
$zip->open('file.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);

// Define paths to exclude (relative to the root folder)
$excludedPaths = [
    'upload/data b',
    'upload/data c'
];

// Create recursive directory iterator
/** @var SplFileInfo[] $files */
$files = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($rootPath),
    RecursiveIteratorIterator::LEAVES_ONLY
);

foreach ($files as $name => $file) {
    // Skip directories (they would be added automatically)
    if (!$file->isDir()) {
        // Get real and relative path for current file
        $filePath = $file->getRealPath();
        $relativePath = substr($filePath, strlen($rootPath) + 1);
        
        // Check if this file is in an excluded directory
        $skipFile = false;
        foreach ($excludedPaths as $excluded) {
            // Match files directly in the excluded dir or subdirs of it
            if (str_starts_with($relativePath, $excluded . DIRECTORY_SEPARATOR) || $relativePath === $excluded) {
                $skipFile = true;
                break;
            }
        }
        
        if ($skipFile) {
            continue; // Skip adding this file
        }
        
        // Add current file to archive
        $zip->addFile($filePath, $relativePath);
    }
}

// Zip archive will be created only after closing object
$zip->close();

Note for PHP versions before 8.0:

str_starts_with() is a PHP 8+ function. If you're on an older version, replace that line with:

if (strpos($relativePath, $excluded . DIRECTORY_SEPARATOR) === 0 || $relativePath === $excluded)

Solution 2: Use a Filtered Iterator (Cleaner & More Efficient)

Instead of checking each file in the loop, we can filter out the unwanted directories at the iterator level. This way, those directories (and all their contents) are never even processed in the first place.

// Get real path for our folder
$rootPath = realpath('folder-to-zip');
// Initialize archive object
$zip = new ZipArchive();
$zip->open('file.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);

// Define paths to exclude (relative to the root folder)
$excludedPaths = [
    'upload/data b',
    'upload/data c'
];

// Create a filter to exclude specific directories
$filteredDirs = new RecursiveCallbackFilterIterator(
    new RecursiveDirectoryIterator($rootPath),
    function ($currentItem, $key, $iterator) use ($rootPath, $excludedPaths) {
        // Get relative path of the current item
        $relativePath = substr($currentItem->getRealPath(), strlen($rootPath) + 1);
        
        // If this is a directory we want to exclude, return false to skip it
        if ($currentItem->isDir()) {
            foreach ($excludedPaths as $excluded) {
                if ($relativePath === $excluded) {
                    return false;
                }
            }
        }
        
        // Allow all other files and directories
        return true;
    }
);

// Use the filtered iterator to loop through files
$files = new RecursiveIteratorIterator(
    $filteredDirs,
    RecursiveIteratorIterator::LEAVES_ONLY
);

foreach ($files as $name => $file) {
    // Skip directories (they would be added automatically)
    if (!$file->isDir()) {
        // Get real and relative path for current file
        $filePath = $file->getRealPath();
        $relativePath = substr($filePath, strlen($rootPath) + 1);
        
        // Add current file to archive
        $zip->addFile($filePath, $relativePath);
    }
}

// Zip archive will be created only after closing object
$zip->close();

This second approach is more efficient because it avoids iterating over files in excluded directories entirely. Both solutions will properly exclude upload/data b and upload/data c from your final ZIP file.

内容的提问来源于stack exchange,提问作者beginnerprogrammer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:46:42