解压缩 .gz 文件并将它们存储在 .tar.gz 存档中
Posted
技术标签:
【中文标题】解压缩 .gz 文件并将它们存储在 .tar.gz 存档中【英文标题】:Uncompressing .gz files and storing them in a .tar.gz archive 【发布时间】:2019-01-02 15:08:40 【问题描述】:我有以下问题:我正在编写一个函数来查找一堆 .gz
文件,解压缩它们,并将单独的未压缩文件存储在更大的 .tar.gz
存档中。到目前为止,我设法使用以下代码实现它,但手动计算未压缩文件大小并设置 TarInfo
大小似乎相当hackish,我想知道是否有更惯用的解决方案来解决我的问题:
import gzip
import os
import pathlib
import tarfile
def gather_compressed_files(input_dir: pathlib.Path, output_file: str):
with tarfile.open(output_file, 'w:gz') as tar:
for input_file in input_dir.glob('*.gz'):
with gzip.open(input_file) as fd:
tar_info = tarfile.TarInfo(input_file.stem)
tar_info.size = fd.seek(0, os.SEEK_END)
fd.seek(0, os.SEEK_SET)
tar.addfile(tar_info, fd)
我尝试通过以下方式创建TarInfo
对象,而不是手动创建它:
tar_info = tar.gettarinfo(arcname=input_file.stem, fileobj=fd)
然而,这个函数检索我们以fd
打开的原始.gz
文件的路径来计算它的大小,因此只提供一个tar_info.size
参数对应于压缩的.gz
数据而不是未压缩的数据,这不是我想要的。根本不设置tar_fino.size
参数也不起作用,因为addfile
在传递文件描述符时使用所述大小。
有没有更好、更惯用的方法来实现这一点,还是我坚持目前的解决方案?
【问题讨论】:
你能举个例子来说明你的尝试吗?所有这些tar.gz
文件是否都存储在一个目录中?是否要将所有这些文件合并到一个 tar.gz
文件中?我只是在验证,所以我正确理解了您的问题。
我有一个包含.gz
文件的目录,我尝试将这些文件单独未压缩地存储在.tar.gz
文件中。
【参考方案1】:
您的方法是避免将文件完全解压缩到磁盘或 RAM 的唯一方法。毕竟添加到tar文件需要提前知道大小,而gzip
文件并不真正知道自己解压后的大小。 The ISIZE
header field 理论上提供解压后的大小,但该字段是在 32 位天定义的,所以它实际上是大小模 2**32
;一个最初大小为 4 GB 的文件和一个大小为 0 B 的文件将具有相同的ISIZE
。无论如何,Python 不会公开ISIZE
,所以即使它有用,也没有内置的方法可以做到这一点(你总是可以用手动解析来搞砸,但这并不完全干净或惯用)。
如果你想避免两次解压文件(一次到seek
转发,一次实际添加到tar文件),以解压到磁盘为代价,你可以使用tempfile.TemporaryFile
来避免两次稍作调整即可解压(无需将原始文件存储在内存中):
import shutil
import tempfile
def gather_compressed_files(input_dir: pathlib.Path, output_file: str):
with tarfile.open(output_file, 'w:gz') as tar:
for input_file in input_dir.glob('*.gz'):
with tempfile.TemporaryFile() as tf:
# Could combine both in one with, but this way we close the gzip
# file ASAP
with gzip.open(input_file) as fd:
shutil.copyfileobj(fd, tf)
tar_info = tarfile.TarInfo(input_file.stem)
tar_info.size = tf.tell()
tf.seek(0)
tar.addfile(tar_info, tf)
【讨论】:
感谢您的回答。ISIZE
不能使用让我有点难过,但我想我们不能拥有我们想玩的所有玩具:)以上是关于解压缩 .gz 文件并将它们存储在 .tar.gz 存档中的主要内容,如果未能解决你的问题,请参考以下文章