Как создать полностью сжатый tar-файл с помощью Python?

107

Как я могу создать файл .tar.gz со сжатием в Python?

Шахджапан
источник
16
tar не сжимает данные, он просто упаковывает файлы вместе. Фактическое сжатие выполняет gzip.
Игнасио Васкес-Абрамс,

Ответы:

186

Чтобы построить .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))

Это создаст сжатый tar-архив, содержащий одну папку верхнего уровня с тем же именем и содержимым, что и source_dir.

Джордж В. Рейли
источник
31
В качестве примечания для читателей, если вы не arcname=os.path.basename(source_dir)укажете, он предоставит вам всю структуру путей source_dirв tar-файле (в большинстве случаев это, вероятно, неудобно).
Brōtsyorfuzthrāx
12
Вторая заметка; использование arcname=os.path.basename(source_dir)still означает, что в архиве есть папка с содержимым source_dir. Если вы хотите, чтобы корень архива содержал само содержимое, а не содержимое папки, используйте arcname=os.path.sepвместо этого.
Jonathan H
2
@Sheljohn, к сожалению, это не совсем правильно, потому что если использовать os.path.sep, то в архиве будет сервис "." или папка «/», что обычно не является проблемой, но иногда это может быть проблемой, если вы позже обработаете этот архив программно. Кажется, единственный настоящий чистый способ - os.walk
Крестный отец
Чтобы избавиться от всей структуры каталогов, просто используйте arcname='.'. Не нужно использовать os.walk.
edouardtheron
85
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».

CNBorn
источник
10
Вам действительно следует использовать with tarfile.open( ..Python, а не вызывать openи closeвручную. То же самое и при открытии обычных файлов.
Jonathan H
31

Вы вызываете tarfile.open с помощьюmode='w:gz' , что означает «Открыть для записи в сжатом gzip».

Вы, вероятно, захотите закончить имя файла ( nameаргумент open) на .tar.gz, но это не влияет на возможности сжатия.

Кстати, вы обычно получаете лучшее сжатие с режимом 'w:bz2', так же как tarобычно может сжиматься даже лучше, bzip2чем с gzip.

Алекс Мартелли
источник
6
Замечу, что имя файла tar-архивов, сжатых с помощью bzip2, должно заканчиваться на ".tar.bz2".
Игнасио Васкес-Абрамс,
8

В предыдущих ответах рекомендуется использовать tarfileмодуль Python для создания .tar.gzфайла в Python. Очевидно, что это хорошее решение в стиле Python, но у него есть серьезный недостаток в скорости архивирования. В этом вопросе упоминается, что tarfileэто примерно в два раза медленнее, чемtar утилита в Linux. По моему опыту, эта оценка вполне верна.

Итак, для более быстрого архивирования вы можете использовать tarкоманду using subprocessmodule:

subprocess.call(['tar', '-czf', output_filename, file_to_archive])
Александр Тукалло
источник
0

В этом tar.gz файл сжимается в каталоге открытого просмотра. В решении используется os.path.basename (file_directory)

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

его использование в файле tar.gz сжать в каталоге

T GTI
источник
0

В дополнение к ответу @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()}")       
Альпер
источник