Python3提取Zip压缩包指定文件夹内容时如何移除父目录?
解决Python zipfile提取子目录内容但不包含父目录的问题
这个问题很常见——当你直接提取带bar/前缀的zip条目时,zipfile模块会完整保留原始的目录结构,导致output-dir下多出一个bar文件夹。下面是两种可靠的解决方案:
方法1:修改ZipInfo的文件名(推荐)
这种方法利用ZipInfo对象的filename属性,直接修改提取后的目标路径,不需要手动处理目录创建:
import zipfile with zipfile.ZipFile('path/to/file.zip', 'r') as archive: output_dir = 'path/to/output-dir' # 筛选出bar/下的所有内容,排除bar/本身这个目录条目 target_items = [item for item in archive.namelist() if item.startswith('bar/') and item != 'bar/'] for item in target_items: # 获取该条目的ZipInfo对象 info = archive.getinfo(item) # 去掉开头的'bar/'前缀,修改目标文件名 info.filename = item[len('bar/'):] # 提取修改后的条目到输出目录 archive.extract(info, output_dir)
原理说明:
namelist()返回zip内所有条目的路径,我们筛选出bar/开头且不是bar/本身的条目(避免创建空的bar目录)。- 修改
ZipInfo.filename后,extract()会将文件直接写入修改后的路径,自动创建所需的子目录(比如dir/会被自动创建来存放file2.txt)。
方法2:手动读取并写入文件
如果你需要更精细的控制(比如自定义权限、过滤文件内容),可以手动读取zip内的文件并写入目标路径:
import zipfile import os with zipfile.ZipFile('path/to/file.zip', 'r') as archive: output_dir = 'path/to/output-dir' for item in archive.namelist(): if item.startswith('bar/') and item != 'bar/': # 计算去掉bar/后的相对路径 relative_path = item[len('bar/'):] # 构造目标文件的完整路径 target_path = os.path.join(output_dir, relative_path) # 确保目标目录存在(比如dir/需要提前创建) os.makedirs(os.path.dirname(target_path), exist_ok=True) # 读取zip内的文件内容并写入目标路径 with archive.open(item) as source_file, open(target_path, 'wb') as dest_file: dest_file.write(source_file.read())
原理说明:
os.makedirs(..., exist_ok=True)确保子目录(比如dir/)被创建,避免写入文件时报错。- 手动读写文件的方式让你可以在提取过程中添加额外逻辑(比如修改文件内容、设置权限)。
为什么你的原始代码会有问题?
你的代码直接提取archive_item到output-dir,zip内的bar/file1.txt会被解析为output-dir/bar/file1.txt——zipfile会严格按照原始路径创建目录结构。通过去掉bar/前缀,我们让文件直接写入output-dir的根目录(或对应的子目录)。
内容的提问来源于stack exchange,提问作者mistyped
相关产品推荐
相关产品推荐

