Jak stworzyć pełny skompresowany plik tar w Pythonie?

107

Jak mogę utworzyć plik .tar.gz z kompresją w Pythonie?

shahjapan
źródło
16
tar nie kompresuje danych, po prostu pakuje pliki razem. To gzip wykonuje właściwą kompresję.
Ignacio Vazquez-Abrams

Odpowiedzi:

186

Aby zbudować .tar.gz(aka .tgz) dla całego drzewa katalogów:

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

Spowoduje to utworzenie archiwum tar spakowanego gzipem, zawierającego pojedynczy folder najwyższego poziomu o tej samej nazwie i zawartości co source_dir.

George V. Reilly
źródło
31
Jako uwaga dla czytelników, jeśli pominiesz, arcname=os.path.basename(source_dir)otrzymasz całą strukturę ścieżek source_dirw pliku tar (w większości sytuacji jest to prawdopodobnie niewygodne).
Brōtsyorfuzthrāx
12
Druga uwaga; użycie arcname=os.path.basename(source_dir)nadal oznacza, że ​​archiwum zawiera folder zawierający zawartość source_dir. Jeśli chcesz, aby katalog główny archiwum zawierał samą zawartość, a nie zawartość folderu, użyj arcname=os.path.sepzamiast tego.
Jonathan H
2
@Sheljohn niestety nie jest to do końca poprawne, bo jeśli ktoś użyje os.path.sep, to archiwum będzie zawierało usługę "." lub folder „/”, co zwykle nie stanowi problemu, ale czasami może to być problem, jeśli później programowo przetworzysz to archiwum. Wydaje się, że jedynym naprawdę czystym sposobem jest robienie os.walki dodawanie plików indywidualnie
The Godfather
Aby pozbyć się całej struktury katalogów, po prostu użyj arcname='.'. Nie ma potrzeby używania 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()

Jeśli chcesz utworzyć skompresowany plik tar.bz2, po prostu zamień rozszerzenie pliku na „.tar.bz2” i „w: gz” na „w: bz2”.

CNBorn
źródło
10
Naprawdę powinieneś używać with tarfile.open( ..w Pythonie, zamiast dzwonić openi closeręcznie. Dzieje się tak również w przypadku otwierania zwykłych plików.
Jonathan H
31

Nazywasz tarfile.open z mode='w:gz', czyli „Otwórz za gzip skompresowanej formie pisemnej.”

Prawdopodobnie będziesz chciał zakończyć nazwę pliku ( nameargument do open) .tar.gz, ale to nie wpływa na możliwości kompresji.

Przy okazji, zwykle uzyskujesz lepszą kompresję w trybie 'w:bz2', tak jak tarzwykle można kompresować nawet lepiej bzip2niż w przypadku gzip.

Alex Martelli
źródło
6
Krótka uwaga, że ​​nazwa pliku dla archiwów skompresowanych za pomocą bzip2 powinna kończyć się na „.tar.bz2”.
Ignacio Vazquez-Abrams
8

Poprzednie odpowiedzi zalecają użycie tarfilemodułu Python do tworzenia .tar.gzpliku w Pythonie. To oczywiście dobre rozwiązanie w stylu Pythona, ale ma poważną wadę w szybkości archiwizacji. To pytanie wspomina, że tarfilejest około dwa razy wolniejsze niż tarnarzędzie w systemie Linux. Z mojego doświadczenia wynika, że ​​ta ocena jest całkiem poprawna.

A więc dla szybszej archiwizacji możesz skorzystać z tarpolecenia za pomocą subprocessmodułu:

subprocess.call(['tar', '-czf', output_filename, file_to_archive])
Aleksandr Tukallo
źródło
0

W tym pliku tar.gz skompresuj w otwartym katalogu widoku W rozwiązaniu użyj 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))

jego użycie w pliku tar.gz skompresuj w katalogu

T GTI
źródło
0

Oprócz odpowiedzi @Aleksandr Tukallo, możesz również uzyskać dane wyjściowe i komunikat o błędzie (jeśli wystąpi). Poniższa odpowiedźtar dość dobrze wyjaśnia kompresję folderu za pomocą .

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
źródło