Как создать архив tar.gz в Python / tar без включения родительского каталога? - PullRequest
0 голосов
/ 17 октября 2019

У меня есть папка A, которая содержит FolderB и FileB. Как я могу создать архив tar.gz, который содержит ТОЛЬКО FolderB и FileB, удаляя родительский каталог FolderA? Я использую Python и запускаю этот код на компьютере с Windows.

Лучшее, что я нашел, было: Как создать полный сжатый tar-файл с использованием Python?

В самом голосуемом ответе люди обсуждают способы удаления родительского каталога, но ни один из них не работает для меня. Я пробовал arcname, os.walk и запускал команду tar через subprocess.call ().

Я близко подошел к os.walk, но в приведенном ниже коде он по-прежнему удаляет каталог "_"в с папками B и FileB. Итак, файловая структура имеет вид ARCHIVE.tar.gz> ARCHIVE.tar> каталог "_", FolderB, FileB.

def make_tarfile(output_filename, source_dir):
    with tarfile.open(output_filename, "w:gz") as tar:
        length = len(source_dir)
        for root, dirs, files in os.walk(source_dir):
            folder = root[length:]  # path without "parent"
            for file in files:
                tar.add(os.path.join(root, folder), folder)

Я делаю архив, используя:

make_tarfile('ARCHIVE.tar.gz', 'C:\FolderA')

СледуетЯ продолжаю использовать os.walk, или есть другой способ решить эту проблему?

Обновление

Вот изображение, показывающее содержимое моего архива. Как выКак видите, в моем архиве есть папка "_", от которой я хочу избавиться - как ни странно, когда я распаковываю, только FolderA и FileB.html отображаются в виде архива. По сути, это правильное поведение, но если бы я мог сделать последний шаг по удалению папки «_» из архива, это было бы идеально. Я собираюсь задать обновленный вопрос, чтобы ограничить путаницу.

Ответы [ 2 ]

0 голосов
/ 17 октября 2019

Вот функция для выполнения задачи. У меня были некоторые проблемы с извлечением tar в Windows (с WinRar ), поскольку казалось, что он пытался извлечь один и тот же файл дважды, но я думаю, что он будет работать нормально при извлечении архива.

"""
The directory structure I have is as follows:

├───FolderA
│   │   FileB
│   │
│   └───FolderB
│           FileC
"""

import tarfile
import os

# This is where I stored FolderA on my computer
ROOT = os.path.join(os.path.dirname(__file__), "FolderA")


def make_tarfile(output_filename: str, source_dir: str) -> bool:
    """ 
    :return: True on success, False otherwise
    """

    # This is where the path to each file and folder will be saved
    paths_to_tar = set()

    # os.walk over the root folder ("FolderA") - note it will never get added
    for dirpath, dirnames, filenames in os.walk(source_dir):

        # Resolve path issues, for example for Windows
        dirpath = os.path.normpath(dirpath)

        # Add each folder and path in the current directory
        # Probably could use zip here instead of set unions but can't be bothered to try to figure it out
        paths_to_tar = paths_to_tar.union(
            {os.path.join(dirpath, d) for d in dirnames}).union(
            {os.path.join(dirpath, f) for f in filenames})

    try:
        # This will create the tar file in the current directory
        with tarfile.open(output_filename, "w:gz") as tar:

            # Change the directory to treat all paths relatively
            os.chdir(source_dir)

            # Finally add each path using the relative path
            for path in paths_to_tar:
                tar.add(os.path.relpath(path, source_dir))
            return True

    except (tarfile.TarError, OSError) as e:
        print(f"An error occurred - {e}")
        return False


if __name__ == '__main__':
    make_tarfile("tarred_files.tar.gz", ROOT)
0 голосов
/ 17 октября 2019

Я попытался привести несколько примеров того, как изменения в исходном каталоге влияют на то, что в итоге извлекается.

В соответствии с вашим примером, у меня есть эта структура папок

enter image description here

У меня есть этот питон для создания файла tar (поднято из здесь )

import tarfile
import os

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-файл, зависит от того, какое местоположение я предоставляю в качестве параметра.

Так что этот параметр местоположения,

make_tarfile('folder.tar.gz','folder_A/' )

сгенерирует этот результат при извлечении

enter image description here

Если я перейду в folder_A и ссылку на folder_B,

make_tarfile('folder.tar.gz','folder_A/folder_B' )

Вот что такое извлечение:

enter image description here

Обратите внимание, что folder_B является корнем этого извлечения.

Теперь, наконец,

make_tarfile('folder.tar.gz','folder_A/folder_B/' )

Извлечет в это

enter image description here

Просто файл включен в извлечение.

...