如何在 Python 中创建压缩的 .tar.gz 文件?
为整个目录树构建
.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
具有相同名称和内容的顶级文件夹。
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”即可。
您使用 mode='w:gz'
调用
tarfile.open,意思是“打开以进行 gzip 压缩写入。”
您可能希望以
name
结尾文件名(open
的 .tar.gz
参数),但这不会影响压缩能力。
顺便说一句,使用
'w:bz2'
模式通常会获得更好的压缩效果,就像 tar
通常使用 bzip2
压缩比使用 gzip
压缩效果更好。
之前的答案建议使用
tarfile
Python 模块在 Python 中创建 .tar.gz
文件。这显然是一个很好的 Python 风格的解决方案,但它在归档速度方面存在严重缺陷。 这个问题提到 tarfile
大约比 Linux 中的 tar
实用程序慢两倍。根据我的经验,这个估计是相当正确的。
因此,为了更快地归档,您可以使用
tar
命令和 subprocess
模块:
subprocess.call(['tar', '-czf', output_filename, file_to_archive])
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
)
除了@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()}")
在这个 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 文件压缩中的使用
对 @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))
我使用它来生成 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}")
只是重申@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))
...如果您不想使用或没有将文件夹路径和文件名分开。
谢谢!🤗
最佳性能,压缩文件中没有
.
和 ..
! 请参阅下面的漏洞警告:
注意(感谢MaxTruxa):
这个答案很容易受到 shell 注入的影响。请阅读文档中的安全注意事项。如果
,切勿将未转义的字符串传递给subprocess.run
、subprocess.call
等。使用shell=True
进行转义(仅限 Unix shell)。shlex.quote
我在本地使用它 - 所以它很适合我的需求。
subprocess.call(f'tar -cvzf {output_filename} *', cwd=source_dir, shell=True)
cwd
参数在压缩之前更改目录 - 这解决了点的问题。
shell=True
允许使用通配符 (*
)
也适用于递归目录