Python tarfile模块读取tar包出现带._前缀重复文件的原因是什么
成因
这些带._前缀的文件是macOS系统生成的AppleDouble格式元数据文件,存储对应文件的扩展属性、资源分支、Finder配置等信息。你使用的压缩包是在macOS环境下打包生成的,不管是用命令行tar打包,还是用macOS右键菜单的「压缩」功能生成压缩包,默认都会写入这类元数据。
macOS自带的BSD tar命令内置了AppleDouble元数据处理逻辑,执行查询、解压操作时会自动隐藏这类元数据条目,解压时直接把元数据写入对应文件的属性,不会生成单独的实体文件,所以你用tar tvf命令看不到这些条目,解压后也没有对应文件。如果把这类压缩包放到Linux系统上用GNU tar操作,会直接看到这些._文件,解压也会生成单独的实体文件。
Python的tarfile模块默认没有内置这类过滤逻辑,会把压缩包内所有条目都读出来,所以会返回6个文件。
解决方法
分为两种场景处理:
- 场景1:还未生成压缩包,可从根源避免元数据写入
打包时在命令前添加COPYFILE_DISABLE=1环境变量即可,命令示例:COPYFILE_DISABLE=1 tar zcvf testing.tar.gz 待打包的文件/目录 - 场景2:已有现成的压缩包,读取时做过滤即可
遍历文件列表时过滤所有文件名以._开头的条目即可,split('/')[-1]的写法可以避免误杀路径中包含._的正常文件,修改后的代码示例:import tarfile infile = '/Users/myname/Downloads/tt/testing.tar.gz' outdir = '/Users/myname/Downloads/tt/out' if tarfile.is_tarfile(infile): # 用with语法可以自动关闭文件句柄,不需要手动调用close with tarfile.open(infile, 'r') as tar_obj: # 过滤元数据文件 valid_names = [ name for name in tar_obj.getnames() if not name.split('/')[-1].startswith('._') ] for name in valid_names: print(name) # 如果需要解压,也基于过滤后的逻辑操作即可 # for tar_info in tar_obj: # if not tar_info.name.split('/')[-1].startswith('._'): # tar_obj.extract(tar_info, outdir)
内容的提问来源于stack exchange,提问作者Bruce Banner
相关产品推荐
相关产品推荐

