如何将文件从 python 中的 tarfile 提取到不同的目标文件名?

How can I extract files to a different destination filename from tarfile in python?

我有一个 tarfile.TarFile,我想从中提取一些文件到修改后的目标文件名;有一个与存档成员同名的现有文件,我不想触及。 具体来说,我想附加一个后缀,例如存档中名为 foo/bar.txt 的成员应提取为 foo/bar.txt.mysuffix.

两个有些明显但也有些不尽如人意的方法是:

TarFile 上是否没有接口或挂钩可以简洁正确地实现这一点?

有TarFile.getmembers() 方法returns 将存档的成员作为列表。 在那里你可以循环并选择你想要提取的文件或 not.Depending 你的 tar 的大小,你的第二种方法也可行但不是最好的。

object = tarfile.open('example.tar', 'r')
for member in object.getmembers():
    if "whatever" in member.name:
        object.extract(member, "example_dir")

浏览Lib/tarfile.py, I came across this comment:

    #--------------------------------------------------------------------------
    # Below are the different file methods. They are called via
    # _extract_member() when extract() is called. They can be replaced in a
    # subclass to implement other functionality.

    def makedir(self, tarinfo, targetpath):
       #...
    
    def makefile(self, tarinfo, targetpath):
       # ...

官方参考文档中没有提到这些方法,但它们似乎是公平的游戏。要在现有打开的 TarFile 实例上覆盖这些,我们可以创建一个子类 Facade/Wrapper:

class SuffixingTarFile(tarfile.TarFile):
    def __init__(self, suffix: str, wrapped: tarfile.TarFile):
        self.suffix = suffix
        self.wrapped = wrapped

    def __getattr__(self, attr):
        return getattr(self.wrapped, attr)

    def makefile(self, tarinfo, targetpath):
        super().makefile(tarinfo, targetpath + self.suffix)

    # overwrite makedir, makelink, makefifo, etc. as desired

示例:

tar = tarfile.open(...)
star = SuffixingTarFile(".foo", tar)
star.extractall()  # extracts all (regular) file members with .foo suffix appended