Como criar um arquivo tar compactado completo usando Python?

107

Como posso criar um arquivo .tar.gz com compressão em Python?

Shahjapan
fonte
16
tar não compacta dados, apenas compacta os arquivos juntos. É o gzip que faz a compressão real.
Ignacio Vazquez-Abrams

Respostas:

186

Para construir um .tar.gz(aka .tgz) para uma árvore de diretório inteira:

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))

Isso criará um arquivo tar compactado com gzip contendo uma única pasta de nível superior com o mesmo nome e conteúdo que source_dir.

George V. Reilly
fonte
31
Apenas como uma nota para os leitores, se você omitir arcname=os.path.basename(source_dir), ele fornecerá toda a estrutura do caminho do source_dirarquivo tar (na maioria das situações, isso é provavelmente inconveniente).
Brōtsyorfuzthrāx
12
Uma segunda nota; usandoarcname=os.path.basename(source_dir) ainda significa que o arquivo contém uma pasta que contém o conteúdo de source_dir. Se quiser que a raiz do arquivo contenha o conteúdo em si, e não o conteúdo de uma pasta, use arcname=os.path.sep.
Jonathan H
2
@Sheljohn infelizmente, isso não está totalmente correto, porque se alguém usar os.path.sep, o arquivo conterá o serviço "." ou a pasta "/" que normalmente não é um problema, mas às vezes pode ser um problema se você processar este arquivo programaticamente posteriormente. Parece que a única maneira realmente limpa é fazer os.walke adicionar arquivos individualmente
The Godfather
Para se livrar de toda a estrutura de diretórios, basta usar arcname='.'. Não há necessidade de usar os.walk.
edouardtheron de
85
import tarfile
tar = tarfile.open("sample.tar.gz", "w:gz")
for name in ["file1", "file2", "file3"]:
    tar.add(name)
tar.close()

Se você deseja criar um arquivo compactado tar.bz2, basta substituir o nome da extensão do arquivo por ".tar.bz2" e "w: gz" por "w: bz2".

CNBorn
fonte
10
Você realmente deve usar with tarfile.open( ..em Python, em vez de chamar opene closemanualmente. Este também é o caso ao abrir arquivos normais.
Jonathan H
31

Você chama tarfile.open commode='w:gz' , que significa "Abrir para gravação compactada gzip."

Você provavelmente vai querer terminar o nome do arquivo (o nameargumento para open) com.tar.gz , mas isso não afeta as habilidades de compactação.

BTW, você geralmente obtém uma melhor compactação com um modo de 'w:bz2', assim como targeralmente pode compactar ainda melhor com bzip2do que com gzip.

Alex Martelli
fonte
6
Apenas uma nota rápida que o nome do arquivo para tarballs compactados com bzip2 deve terminar com ".tar.bz2".
Ignacio Vazquez-Abrams
8

As respostas anteriores aconselham o uso do tarfilemódulo Python para criar um .tar.gzarquivo em Python. Obviamente, essa é uma boa solução no estilo Python, mas tem uma séria desvantagem na velocidade de arquivamento. Esta questão menciona que tarfileé aproximadamente duas vezes mais lento que otar utilitário do Linux. De acordo com minha experiência, essa estimativa é bastante correta.

Portanto, para um arquivamento mais rápido, você pode usar o tarcomando using subprocessmodule:

subprocess.call(['tar', '-czf', output_filename, file_to_archive])
Aleksandr Tukallo
fonte
0

Neste arquivo tar.gz, compactar no diretório de visualização aberta. Em solve use 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))

seu uso no arquivo tar.gz compactado no diretório

T GTI
fonte
0

Além da resposta de @Aleksandr Tukallo, você também pode obter a saída e a mensagem de erro (se ocorrer). A compactação de uma pasta usando taré explicada muito bem na resposta a seguir .

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()}")       
Alper
fonte