我想用 Python 的分层目录结构创建一个 tar 存档,使用字符串作为文件的内容。我读过这个问题,它显示了一种将字符串添加为文件的方法,而不是作为目录。如何在不实际制作目录的情况下将目录动态添加到 tar 存档中?
就像是:
archive.tgz:
file1.txt
file2.txt
dir1/
file3.txt
dir2/
file4.txt
扩展链接问题中给出的示例,您可以执行以下操作:
import tarfile
import StringIO
import time
tar = tarfile.TarFile("test.tar", "w")
string = StringIO.StringIO()
string.write("hello")
string.seek(0)
info = tarfile.TarInfo(name='dir')
info.type = tarfile.DIRTYPE
info.mode = 0755
info.mtime = time.time()
tar.addfile(tarinfo=info)
info = tarfile.TarInfo(name='dir/foo')
info.size=len(string.buf)
info.mtime = time.time()
tar.addfile(tarinfo=info, fileobj=string)
tar.close()
请注意mode
属性,因为默认值可能不包括目录所有者的执行权限,需要更改目录并获取其内容。
对有用的已接受答案稍作修改,使其适用于 python 3 和 python 2(并且与 OP 的示例更接近):
from io import BytesIO
import tarfile
import time
# create and open empty tar file
tar = tarfile.open("test.tgz", "w:gz")
# Add a file
file1_contents = BytesIO("hello 1".encode())
finfo1 = tarfile.TarInfo(name='file1.txt')
finfo1.size = len(file1_contents.getvalue())
finfo1.mtime = time.time()
tar.addfile(tarinfo=finfo1, fileobj=file1_contents)
# create directory in the tar file
dinfo = tarfile.TarInfo(name='dir')
dinfo.type = tarfile.DIRTYPE
dinfo.mode = 0o755
dinfo.mtime = time.time()
tar.addfile(tarinfo=dinfo)
# add a file to the new directory in the tar file
file2_contents = BytesIO("hello 2".encode())
finfo2 = tarfile.TarInfo(name='dir/file2.txt')
finfo2.size = len(file2_contents.getvalue())
finfo2.mtime = time.time()
tar.addfile(tarinfo=finfo2, fileobj=file2_contents)
tar.close()
特别是,我按照PEP 3127 -- Integer Literal Support and Syntax更新了八进制语法,切换到BytesIO from io
,使用getvalue
而不是buf
,并使用open
而不是TarFile
显示压缩输出,如示例中所示。(上下文处理程序用法(with ... as tar:
)也适用于 python2 和 python3,但剪切和粘贴不适用于我的 python2 repl,所以我没有切换它。)在 python 2.7.15+ 和 python 3.7.3 上测试。
查看tar 文件格式似乎可行。每个子目录中的文件都以相对路径名(例如dir1/file3.txt
)作为它们的名称。
唯一的诀窍是您必须在进入其中的文件之前定义每个目录(tar
不会即时创建必要的子目录)。有一个特殊标志可用于将 tarfile 条目标识为目录,但出于遗留目的,tar
也接受名称/
以代表目录结尾的文件条目,因此您应该能够dir1/
从零添加为文件-长度字符串使用相同的技术。