簡體   English   中英

如何使用python的tarfile模塊創建文件夾然后在tar中歸檔

[英]How to create a folder and then file in tar using tarfile module of python

Python源代碼

   #!/usr/bin/env python3
"Utility to create .deb files."

import argparse
import io
import json
import os
import subprocess
import sys
import tarfile
import tempfile

def validate_manifest(manifest):
    "Validate that the package manifest makes sense."
    for prop in 'name', 'version', 'files':
        if prop not in manifest:
            sys.exit('Missing mandatory "' + prop + '" property')

    if manifest['arch'] not in ['all', 'arm', 'i686', 'aarch64', 'x86_64']:
        sys.exit('Invalid "arch" - must be one of all/arm/i686/aarch64/x86_64')

def set_default_value(manifest, property_name, default_value):
    "Set a default property value if one does not exist."
    if property_name not in manifest:
        manifest[property_name] = default_value

def setup_default_manifest_values(manifest):
    "Setup default values in a package manifest."
    set_default_value(manifest, 'arch', 'all')
    set_default_value(manifest, 'conflicts', [])
    set_default_value(manifest, 'depends', [])
    set_default_value(manifest, 'description', 'No description')
    set_default_value(manifest, 'maintainer', 'None')
    set_default_value(manifest, 'provides', [])

def write_control_tar(tar_path, manifest):
    "Create a data.tar.xz from the specified manifest."
    contents = 'Package: ' + manifest['name'] + "\n"
    contents += 'Version: ' + manifest['version'] + "\n"
    contents += 'Architecture: ' + manifest['arch'] + "\n"
    contents += 'Maintainer: ' + manifest['maintainer'] + "\n"
    contents += 'Description: ' + manifest['description'] + "\n"

    if 'homepage' in manifest:
        contents += 'Homepage: ' + manifest['homepage'] + "\n"

    if manifest['depends']:
        contents += 'Depends: ' + ','.join(manifest['depends']) + '\n'
    if manifest['provides']:
        contents += 'Provides: ' + ','.join(manifest['provides']) + '\n'
    if manifest['conflicts']:
        contents += 'Conflicts: ' + ','.join(manifest['conflicts']) + '\n'

    control_file = io.BytesIO(contents.encode('utf8'))
    control_file.seek(0, os.SEEK_END)
    file_size = control_file.tell()
    control_file.seek(0)

    info = tarfile.TarInfo(name="control")
    info.size = file_size
    with tarfile.open(tar_path, mode='w:xz') as control_tarfile:
        control_tarfile.addfile(tarinfo=info, fileobj=control_file)

def write_data_tar(tar_path, installation_prefix, package_files):
    "Create a data.tar.xz from the specified package files."
    with tarfile.open(tar_path, mode='w:xz') as data_tarfile:
        for input_file_path in package_files:
            file_stat = os.stat(input_file_path)

            # The tar file path should not start with slash:
            if installation_prefix.startswith('/'):
                installation_prefix = installation_prefix[1:]
            if not installation_prefix.endswith('/'):
                installation_prefix += '/'

            output_file = installation_prefix + package_files[input_file_path]
            info = tarfile.TarInfo(name=output_file)

            info.mode = file_stat.st_mode
            info.mtime = file_stat.st_mtime
            info.size = file_stat.st_size
            with open(input_file_path, 'rb') as input_file:
                data_tarfile.addfile(tarinfo=info, fileobj=input_file)

def create_debfile(debfile_output, directory):
    "Create a debfile from a directory containing control and data tar files."
    subprocess.check_call(['ar', 'r', debfile_output,
                           directory + '/debian-binary',
                           directory + '/control.tar.xz',
                           directory + '/data.tar.xz'
                          ])

DESCRIPTION = """Create a package from a JSON manifest file. Example of manifest:
{
  "name": "mypackage",
  "version": "0.1",
  "arch": "all",
  "maintainer": "@MyGithubNick",
  "description": "This is a hello world package",
  "homepage": "https://example.com",
  "depends": ["python", "vim"],
  "provides": ["vi"],
  "conflicts": ["vim-python-git"],
  "files" : {
    "hello-world.py": "bin/hello-world",
    "hello-world.1": "share/man/man1/hello-world.1"
  }
}
The "maintainer", "description", "homepage", "depends", "provides" and "conflicts" fields are all optional.
The "depends" field should be a comma-separated list of packages that this package depends on. They will be installed automatically when this package is installed using apt.
The "arch" field defaults to "all" (that is, a platform-independent package not containing native code) and can be any of arm/i686/aarch64/x86_64.  Run "uname -m" to find out arch name if building native code inside.
The "files" map is keyed from paths to files to include (relative to the current directory) while the values contains the paths where the files should end up after installation (relative to $PREFIX).
The resulting .deb file can be installed by users with:
  apt install ./package-file.deb
or by hosting it in an apt repository using the repo tool."""

def main(argv):
    "Generate a deb file from a JSON manifest."
    installation_prefix = "/usr/"

    parser = argparse.ArgumentParser(description=DESCRIPTION,
                                     formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument("manifest", help="a JSON manifest file describing the package")
    parser.add_argument("--prefix", help="set prefix dir (default: " + installation_prefix + ")")
    args = parser.parse_args(argv)

    if args.prefix:
        installation_prefix = str(args.prefix)

    manifest_file_path = args.manifest

    with open(manifest_file_path, 'r') as manifest_file:
        manifest = json.load(manifest_file)

    setup_default_manifest_values(manifest)
    validate_manifest(manifest)

    package_name = manifest['name']
    package_version = manifest['version']
    package_files = manifest['files']

    output_debfile_name = package_name + '_' + package_version + '_' + manifest['arch'] + '.deb'
    print('Building ' + output_debfile_name)

    package_tmp_directory = tempfile.TemporaryDirectory()
    with open(package_tmp_directory.name + '/debian-binary', 'w') as debian_binary:
        debian_binary.write("2.0\n")

    write_control_tar(package_tmp_directory.name + '/control.tar.xz', manifest)
    write_data_tar(package_tmp_directory.name + '/data.tar.xz', installation_prefix, package_files)
    create_debfile(output_debfile_name, package_tmp_directory.name)

if __name__ == "__main__":
    main(sys.argv[1:])

目前,此腳本使用創建了control.tar.xz ,但是我想在創建control.tar.xz時添加一個文件夾,然后將控制文件添加到該文件夾​​中。

表示當前層次結構是

control.tar.xz ==>控制文件

我想要這個等級

control.tar.xz ==>文件夾名稱==>控制文件

基本上,tar文件不僅包含控制文件,還包含目錄和該目錄內的控制文件。

我將stackoverflow答案修改為tardata.py ,它查找control.txt並將其放置在data目錄中並調用提取的文件control.tar.gz

import os
import tarfile

tar_file = "control.tar.gz"
source_file = "control.txt"
inside_dir = "data"

def make_tarfile(tar_file, source_file, inside_dir):
    with tarfile.open(tar_file, "w:gz") as tar:
        tar.add(source_file, arcname=os.path.join(inside_dir, source_file))

make_tarfile(tar_file, source_file, inside_dir)

該代碼使用可選的參數arcname ,該參數允許在tar文件中創建目錄。 tarfile.Add()文檔

如果提供了arcname,則為歸檔文件中的文件指定備用名稱。

$ python tardata.py

檢查創建的tar文件的層次結構

$ tar --list -f control.tar.gz
data/control.txt

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM