如何使用Python将文件添加到tar文件中,而不添加目录结构?

82
当我在一个tarfile对象上调用add()方法并传入文件路径时,该文件会以关联的目录层次结构添加到tarball中。换句话说,如果我解压缩tarfile,原始目录层次结构中的目录会被复制。

有没有一种方法可以简单地添加一个普通文件,而不带有目录信息,以便解压缩生成的tarball会产生一个扁平的文件列表?


对于那些需要保留目录结构的部分的人来说,可以查看shutil.make_archive()函数,特别是root_dirbase_dir参数。请参考文档中的示例和例如这个 - undefined
6个回答

109

使用TarFile.add()方法的arcname参数是一种替代和方便的匹配目标的方法。

例如:你想将目录repo/a.git/归档到一个tar.gz文件中,但你更希望在存档中根目录以a.git/而不是repo/a.git/开头,你可以像下面这样做:

archive = tarfile.open("a.git.tar.gz", "w|gz")
archive.add("repo/a.git", arcname="a.git")
archive.close()

这是更好的方法,因为如果你要添加目录,被接受的答案将不起作用。 - Ganesh Hegde
5
arcname ="a.git" 将在归档文件中创建一个名为 a.git 的文件夹。您可以使用 arcname ="" 在不创建文件夹的情况下将文件归档到 repo/a.git 目录中。 - Comrade Che
@ComradeChe的回答给出了错误的结果:生成的tar文件只包含一个文件。 因此,为添加到tar文件中的每个文件提供清晰的文件名(不包括路径)作为arcname。 - Alexey Antonenko
相反,我认为ComradeChe的回答是正确的,@Alexey Antonenko能否提供一个例子? - undefined

61

您可以使用tarfile.addfile(),在TarInfo对象中,第一个参数中指定一个与添加的文件不同的name

这段代码应该将/path/to/filename添加到TAR文件中,但将其提取为myfilename

tar.addfile(tarfile.TarInfo("myfilename.txt"), open("/path/to/filename.txt"))

45
同时,tar.add()方法同样适用!若要添加整个目录树,并使用不同的名称,只需执行:tar.add('/path/to/dir/to/add/', arcname='newdirname'),然后tar文件将包含一个名为“newdirname”的目录,其中包含所有内容都未经修改。 - Armando Pérez Marqués
21
如果你想将文件保存在没有目录结构的情况下,请使用arcname='.' - Giacomo Tagliabue
file() 只适用于 Python 2,open() 是等效的,并且在 Python 2 和 3 中都可以使用。我编辑了我的答案以使用 open - Wim
3
由于某些原因,我的机器只创建了一份包含空文件的tar归档文件(文件存在,但为空)。 - Roland Pihlakas
2
使用 arcname='.' 时,我尝试解压和提取内容时遇到了 IsADirectoryError。不过,使用下面 @diabloneo 的答案就可以了。 - rer
显示剩余2条评论

8
也许您可以使用TarFile.add(name, arcname)中的“arcname”参数。它可以指定文件在存档中的备用名称。

3
感谢 @diabloneo,这是一个创建目录选择性tar包的函数。
def compress(output_file="archive.tar.gz", output_dir='', root_dir='.', items=[]):
    """compress dirs.

    KWArgs
    ------
    output_file : str, default ="archive.tar.gz"
    output_dir : str, default = ''
        absolute path to output
    root_dir='.',
        absolute path to input root dir
    items : list
        list of dirs/items relative to root dir

    """
    os.chdir(root_dir)
    with tarfile.open(os.path.join(output_dir, output_file), "w:gz") as tar:
        for item in items:
            tar.add(item, arcname=item)    


>>>root_dir = "/abs/pth/to/dir/"
>>>compress(output_file="archive.tar.gz", output_dir=root_dir, 
            root_dir=root_dir, items=["logs", "output"])

你应该始终将 os.chdir 与 try finally 一起使用,以返回到旧的工作目录,因为库代码不应该更改工作目录。 - schlamar

1

以下是示例代码,用于在不添加文件夹的情况下压缩文件夹中的文件列表:

    with tarfile.open(tar_path, 'w') as tar:
        for filename in os.listdir(folder):
            fpath = os.path.join(folder, filename)
            tar.add(fpath, arcname=filename)

-3
如果您想将目录名称添加到tar文件中,但不包括其内容,可以执行以下操作:
(1) 创建一个名为empty的空目录 (2) tf.add("empty", arcname=path_you_want_to_add) 这将创建一个名为path_you_want_to_add的空目录。

原帖要求包含没有目录的文件。你的回答回答了一个不同的问题。请修改你的回答以回答原帖的问题。或者将其作为评论添加,而不是作为答案。 - Allen M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接