如何使用Python创建完整压缩的tar文件?

问题描述 投票:0回答:11

如何在 Python 中创建压缩的 .tar.gz 文件?

python compression zip tarfile
11个回答
308
投票

为整个目录树构建

.tar.gz
(又名
.tgz
):

import tarfile
import os.path

def make_tarfile(output_filename, source_dir):
    with tarfile.open(output_filename, "w:gz") as tar:
        tar.add(source_dir, arcname=os.path.basename(source_dir))

这将创建一个 gzip 压缩的 tar 存档,其中包含一个与

source_dir
具有相同名称和内容的顶级文件夹。


114
投票
import tarfile
tar = tarfile.open("sample.tar.gz", "w:gz")
for name in ["file1", "file2", "file3"]:
    tar.add(name)
tar.close()

如果要创建 tar.bz2 压缩文件,只需将文件扩展名替换为“.tar.bz2”,将“w:gz”替换为“w:bz2”即可。


35
投票

您使用 mode='w:gz' 调用

tarfile.open
,意思是“打开以进行 gzip 压缩写入。”

您可能希望以

name
结尾文件名(
open
.tar.gz
参数),但这不会影响压缩能力。

顺便说一句,使用

'w:bz2'
模式通常会获得更好的压缩效果,就像
tar
通常使用
bzip2
压缩比使用
gzip
压缩效果更好。


25
投票

之前的答案建议使用

tarfile
Python 模块在 Python 中创建
.tar.gz
文件。这显然是一个很好的 Python 风格的解决方案,但它在归档速度方面存在严重缺陷。 这个问题提到
tarfile
大约比 Linux 中的
tar
实用程序慢两倍。根据我的经验,这个估计是相当正确的。

因此,为了更快地归档,您可以使用

tar
命令和
subprocess
模块:

subprocess.call(['tar', '-czf', output_filename, file_to_archive])

7
投票

shutil.make_archive对于文件和目录都非常方便(内容递归添加到存档中):

import shutil

compressed_file = shutil.make_archive(
        base_name='archive',   # archive file name w/o extension
        format='gztar',        # available formats: zip, gztar, bztar, xztar, tar
        root_dir='path/to/dir' # directory to compress
)

3
投票

除了@Aleksandr Tukallo 的答案之外,您还可以获得输出和错误消息(如果发生)。使用

tar
压缩文件夹在以下答案中得到了很好的解释。

import traceback
import subprocess

try:
    cmd = ['tar', 'czfj', output_filename, file_to_archive]
    output = subprocess.check_output(cmd).decode("utf-8").strip() 
    print(output)          
except Exception:       
    print(f"E: {traceback.format_exc()}")       

2
投票

在这个 tar.gz 文件压缩在打开的视图目录中 在解决时使用 os.path.basename(file_directory)

import tarfile

with tarfile.open("save.tar.gz","w:gz") as tar:
      for file in ["a.txt","b.log","c.png"]:
           tar.add(os.path.basename(file))

它在目录中的 tar.gz 文件压缩中的使用


0
投票

对 @THAVASI.T 的答案进行了小修正,省略了显示“tarfile”库的导入,并且没有定义第三行中使用的“tar”对象。

import tarfile

with tarfile.open("save.tar.gz","w:gz") as tar:
    for file in ["a.txt","b.log","c.png"]:
        tar.add(os.path.basename(file))

0
投票

我使用它来生成 tar.gz 文件,而不包含主文件夹。

import tarfile
import os.path

source_location = r'C:\Users\username\Desktop\New folder'
output_name = r'C:\Users\username\Desktop\new.tar.gz'

# ---------------------------------------------------
#  --- output new.tar.gz with 'New folder' inside ---
#  -> new.tar.gz/New folder/aaaa/a.txt 
#  -> new.tar.gz/New folder/bbbb/b.txt
# ---------------------------------------------------
# def make_tarfile(output_filename, source_dir):
#     with tarfile.open(output_filename, "w:gz") as tar:
#         # tar.add(source_dir, arcname=os.path.basename(source_dir))
#         tar.add(source_dir, arcname=os.path.sep(source_dir))


# ---------------------------------------------------
#  --- output new.tar.gz without 'New folder' inside ---
#  -> new.tar.gz/aaaa/a.txt 
#  -> new.tar.gz/bbbb/b.txt
# ---------------------------------------------------
def make_tarfile(output_filename, source_dir):
    with tarfile.open(output_filename, "w:gz") as tar:
        for root, _, files in os.walk(source_dir):
            for file in files:
                file_path = os.path.join(root, file)
                arcname = os.path.relpath(file_path, source_dir)
                tar.add(file_path, arcname=arcname)

try:
    make_tarfile(output_name, source_location)

except Exception as e:
    print(f"Error: {e}")

-1
投票

只是重申@George V. Reilly 的出色答案,但以更清晰的形式......

import tarfile


fd_path="/some/folder/path/"
fl_name="some_file_name.ext"
targz_fd_path_n_fl_name="/some/folder/path/some_file_name.tar.gz"

with tarfile.open(targz_fd_path_n_fl_name, "w:gz") as tar:
    tar.add(fd_path + fl_name, fl_name)

正如 @Brōtsyorfuzthrāx 指出的(但以另一种方式),如果您保留“add”方法的第二个参数,那么它将为您提供 tar 文件中

fd_path + fl_name
的整个路径结构。

当然你可以使用...

import tarfile
import os

fd_path_n_fl_name="/some/folder/path/some_file_name.ext"
targz_fd_path_n_fl_name="/some/folder/path/some_file_name.tar.gz"

with tarfile.open(targz_fd_path_n_fl_name, "w:gz") as tar:
    tar.add(fd_path_n_fl_name, os.path.basename(fd_path_n_fl_name))

...如果您不想使用或没有将文件夹路径和文件名分开。

谢谢!🤗


-5
投票

最佳性能,压缩文件中没有

.
..
请参阅下面的漏洞警告:

注意(感谢MaxTruxa):

这个答案很容易受到 shell 注入的影响。请阅读文档中的安全注意事项。如果

subprocess.run
,切勿将未转义的字符串传递给
subprocess.call
shell=True
等。使用
shlex.quote
进行转义(仅限 Unix shell)。

我在本地使用它 - 所以它很适合我的需求。

subprocess.call(f'tar -cvzf {output_filename} *', cwd=source_dir, shell=True)

cwd
参数在压缩之前更改目录 - 这解决了点的问题。

shell=True
允许使用通配符 (
*
)

也适用于递归目录

© www.soinside.com 2019 - 2024. All rights reserved.