tarfile —读写 tar 存档文件

源代码: Lib/tarfile.py


tarfile模块可以读取和写入 tarFiles,包括使用 gzip,bz2 和 lzma 压缩的 Files。使用zipfile模块读取或写入.zip文件,或使用shutil中的更高级Function。

一些事实和数据:

  • 如果各个模块可用,则读取和写入gzipbz2lzma压缩 Files。

  • 对 POSIX.1-1988(ustar)格式的读/写支持。

  • 对 GNU tar 格式(包括* longname longlink extensions)的读/写支持,对 sparse *extensions 的所有变体的只读支持,包括恢复稀疏文件。

  • 对 POSIX.1-2001(pax)格式的读/写支持。

  • 处理目录,常规文件,硬链接,符号链接,fifo,字符设备和块设备,并能够获取和恢复文件信息,例如时间戳,访问权限和所有者。

在版本 3.3 中进行了更改:添加了对lzma压缩的支持。

  • tarfile. open(* name = None mode ='r' fileobj = None bufsize = 10240 ** kwargs *)
  • mode *必须是格式为'filemode[:compression]'的字符串,默认为'r'。这是模式组合的完整列表:
modeaction
'r' or 'r:*'打开以透明压缩方式阅读(推荐)。
'r:'仅打开即可阅读,无需压缩。
'r:gz'pass gzip 压缩打开以供阅读。
'r:bz2'打开以使用 bzip2 压缩进行阅读。
'r:xz'开放使用 lzma 压缩进行阅读。
'x''x:'仅创建不压缩的 tarfile。引发FileExistsError异常(如果已存在)。
'x:gz'使用 gzip 压缩创建 tarfile。引发FileExistsError异常(如果已存在)。
'x:bz2'使用 bzip2 压缩创建一个 tarfile。引发FileExistsError异常(如果已存在)。
'x:xz'使用 lzma 压缩创建一个 tarfile。引发FileExistsError异常(如果已存在)。
'a' or 'a:'打开以进行追加而没有压缩。如果文件不存在,则创建该文件。
'w' or 'w:'打开以进行未压缩的写入。
'w:gz'打开以进行 gzip 压缩书写。
'w:bz2'打开以进行 bzip2 压缩写入。
'w:xz'为 lzma 压缩写打开。

注意'a:gz''a:bz2''a:xz'是不可能的。如果* mode 不适合打开某个(压缩的)文件进行读取,则会引发ReadError。使用 mode * 'r'避免这种情况。如果不支持压缩方法,则会引发CompressionError

如果指定了* fileobj ,它将用作以二进制形式为 name *打开的file object的替代。它应该位于位置 0.

对于模式'w:gz''r:gz''w:bz2''r:bz2''x:gz''x:bz2'tarfile.open()接受关键字参数* compresslevel *(默认为9)来指定文件的压缩级别。

出于特殊目的,* mode 还有第二种格式:'filemode|[compression]'tarfile.open()将返回一个TarFile对象,该对象将其数据作为块流处理。不会对文件进行随机查找。如果给定, fileobj 可以是具有read()write()方法的任何对象(取决于 mode *)。 * bufsize *指定块大小,默认为20 * 512个字节。结合使用此变体,例如sys.stdin,套接字file object或磁带设备。但是,这样的TarFile对象受到限制,因为它不允许随机访问,请参见Examples。当前可能的模式:

ModeAction
'r|*'打开 tar 数据块流以透明压缩方式进行读取。
'r|'打开未压缩的 tar 块的“流”以进行读取。
'r|gz'打开一个 gzip 压缩的* stream *进行阅读。
'r|bz2'打开一个 bzip2 压缩的* stream *进行读取。
'r|xz'打开一个 lzma 压缩的* stream *进行读取。
'w|'打开未压缩的* stream *进行写入。
'w|gz'打开一个压缩的* stream * gzip 进行编写。
'w|bz2'打开一个 bzip2 压缩的* stream *进行写入。
'w|xz'打开一个 lzma 压缩的* stream *进行写入。

在版本 3.5 中进行了更改:添加了'x'(独占创建)模式。

在版本 3.6 中更改:* name *参数接受path-like object

  • 类别 tarfile. TarFile

  • tarfile. is_tarfile(* name *)

    • 如果* name *是 tar 存档文件,则返回Truetarfile模块可以读取该文件。

tarfile模块定义以下异常:

  • exception tarfile. TarError

    • 所有tarfile个 exception 的 Base Class。
  • exception tarfile. ReadError

    • 在打开 tar 归档文件时引发,该归档文件不能由tarfile模块处理,或者由于某种原因无效。
  • exception tarfile. CompressionError

    • 当不支持压缩方法或无法正确解码数据时引发。
  • exception tarfile. StreamError

    • 针对类似流的TarFile对象的典型限制而提出。
  • exception tarfile. ExtractError

    • 在使用TarFile.extract()时引发非致命错误,但仅在TarFile.errorlevel == 2时引发。
  • exception tarfile. HeaderError

以下常量在模块级别可用:

以下每个常量定义tarfile模块能够创建的 tar 存档格式。有关详情,请参见支持的 tar 格式部分。

  • tarfile. USTAR_FORMAT

    • POSIX.1-1988(ustar)格式。
  • tarfile. GNU_FORMAT

    • GNU tar 格式。
  • tarfile. PAX_FORMAT

    • POSIX.1-2001(pax)格式。
  • tarfile. DEFAULT_FORMAT

    • 用于创建 Files 的默认格式。当前是PAX_FORMAT

在版本 3.8 中更改:新 Files 的默认格式已从GNU_FORMAT更改为PAX_FORMAT

See also

TarFile Objects

TarFile对象提供 tar 存档的接口。 tar 存档是一系列块。存档成员(存储的文件)由标题块和数据块组成。可以将文件多次存储在 tar 归档中。每个存档成员由TarInfo对象表示,有关详细信息,请参见TarInfo Objects

TarFile对象可用作with语句中的上下文 Management 器。块完成后,它将自动关闭。请注意,如果发生 exceptions,打开的存档归档文件将不会finally确定;仅内部使用的文件对象将被关闭。有关用例,请参见Examples部分。

版本 3.2 中的新Function:添加了对上下文 Management 协议的支持。

    • class * tarfile. TarFile((name = None mode ='r' fileobj = None format = DEFAULT_FORMAT tarinfo = TarInfo dereference = False ignore_zeros = False , * encoding = ENCODING errors ='surrogateescape',* pax_headers = None debug = 0 errorlevel = 0 *)
    • 以下所有自变量都是可选的,也可以作为实例属性进行访问。
  • name 是归档文件的路径名。 名称可能是path-like object。如果给出 fileobj *,可以Ellipsis。在这种情况下,将使用文件对象的name属性(如果存在)。

  • mode *是'r'以从现有存档中读取,以将数据追加到现有文件中,'w'以创建一个覆盖现有文件的新文件,或'x'仅创建不存在的新文件。

如果给出* fileobj ,则用于读取或写入数据。如果可以确定,则 mode fileobj *的 mode 覆盖。 * fileobj *将从位置 0 开始使用。

Note

TarFile关闭时,* fileobj *没有关闭。

  • format *控制用于写入的存档格式。它必须是在模块级别定义的常量USTAR_FORMATGNU_FORMATPAX_FORMAT之一。读取时,即使单个存档中存在不同的格式,也会自动检测格式。

  • tarinfo *参数可用于将默认的TarInfo类替换为另一类。

如果* dereference *为False,则将符号链接和硬链接添加到存档。如果为True,则将目标文件的内容添加到存档中。这对不支持符号链接的系统没有影响。

如果* ignore_zeros *为False,则将一个空块视为存档的结尾。如果是True,请跳过空的(和无效的)块,并try获取尽可能多的成员。这仅对读取串联或损坏的 Files 有用。

  • debug *可以设置为0(无调试消息)到3(所有调试消息)。消息被写入sys.stderr

如果* errorlevel 0,则使用TarFile.extract()时将忽略所有错误。但是,启用调试后,它们将作为错误消息出现在调试输出中。如果1,则所有致命*错误都将引发OSError个异常。如果为2,则所有非致命错误也会作为TarError异常引发。

  • encoding errors *参数定义用于读取或写入 Files 的字符编码,以及如何处理转换错误。默认设置适用于大多数用户。有关详细信息,请参见第Unicode issues节。

  • pax_headers 参数是可选的字符串字典,如果 format *为PAX_FORMAT,则它将作为 pax 全局标题添加。

在版本 3.2 中更改:使用'surrogateescape'作为* errors *参数的默认值。

在版本 3.5 中进行了更改:添加了'x'(独占创建)模式。

在版本 3.6 中更改:* name *参数接受path-like object

  • 类方法 TarFile. open(* ... *)

    • 替代构造函数。 tarfile.open()函数实际上是该类方法的快捷方式。
  • TarFile. getmember(* name *)

    • 返回成员* name TarInfo对象。如果在存档中找不到 name *,则引发KeyError

Note

如果成员在存档中出现多次,则假定其最后一次出现是最新版本。

  • TarFile. getmembers ( )

    • TarInfo对象列表的形式返回存档的成员。该列表与存档中的成员具有相同的 Sequences。
  • TarFile. getnames ( )

    • 将成员作为其姓名列表返回。它与getmembers()返回的列表具有相同的 Sequences。
  • TarFile. list(* verbose = True **,* members = None *)

    • 将目录打印到sys.stdout。如果* verbose False,则仅打印成员的名称。如果是True,则产生类似于 ls -l 的输出。如果给出了可选的 members *,则它必须是getmembers()返回的列表的子集。

在版本 3.5 中进行了更改:添加了* members *参数。

  • TarFile. next ( )

    • 打开TarFile进行读取时,将存档的下一个成员作为TarInfo对象返回。如果没有更多可用,则返回None
  • TarFile. extractall(* path =“.” members = None **,* numeric_owner = False *)

    • 从存档中提取所有成员到当前工作目录或目录* path 。如果给出了可选的 members *,则它必须是getmembers()返回的列表的子集。在提取所有成员之后,将设置目录信息,如所有者,修改时间和权限。这样做是为了解决两个问题:每次在目录中创建文件时,都会重置目录的修改时间。而且,如果目录的权限不允许写入,则将文件提取到该目录将失败。

如果* numeric_owner *为True,则使用 tarfile 中的 uid 和 gid 数字设置提取文件的所有者/组。否则,将使用 tarfile 中的命名值。

Warning

未经事先检查,切勿从不受信任的来源中提取 Files。文件可能是在* path *之外创建的,例如具有以"/"开头的绝对文件名或带有两个点".."的文件名的成员。

在版本 3.5 中进行了更改:添加了* numeric_owner *参数。

在版本 3.6 中更改:* path *参数接受path-like object

  • TarFile. extract(* member path =“” set_attrs = True **,* numeric_owner = False *)
    • 使用成员的全名将成员从存档中提取到当前工作目录。尽可能准确地提取其文件信息。 * member 可以是文件名或TarInfo对象。您可以使用 path *指定其他目录。 * path 可能是path-like object。除非 set_attrs *为 false,否则将设置文件属性(所有者,mtime,模式)。

如果* numeric_owner *为True,则使用 tarfile 中的 uid 和 gid 数字设置提取文件的所有者/组。否则,将使用 tarfile 中的命名值。

Note

extract()方法无法解决多个提取问题。在大多数情况下,您应该考虑使用extractall()方法。

Warning

请参阅extractall()的警告。

在版本 3.2 中进行了更改:添加了* set_attrs *参数。

在版本 3.5 中进行了更改:添加了* numeric_owner *参数。

在版本 3.6 中更改:* path *参数接受path-like object

  • TarFile. extractfile(成员)
    • 从存档中提取一个成员作为文件对象。 * member 可以是文件名或TarInfo对象。如果 member *是常规文件或链接,则返回io.BufferedReader对象。否则,返回None

在版本 3.3 中更改:返回io.BufferedReader对象。

  • TarFile. add(* name arcname = None recursive = True **,* filter = None *)
    • 将文件* name *添加到存档中。 * name 可以是任何类型的文件(目录,fifo,符号链接等)。如果给定,则 arcname 指定存档中文件的备用名称。默认情况下,将以递归方式添加目录。可以pass将 recursive 设置为False来避免这种情况。递归按排序 Sequences 添加条目。如果给定 filter *,它应该是一个带有TarInfo对象参数并返回更改后的TarInfo对象的函数。如果改为返回None,则TarInfo对象将从存档中排除。有关示例,请参见Examples

在版本 3.2 中进行了更改:添加了* filter *参数。

在 3.7 版中进行了更改:递归按排序 Sequences 添加条目。

  • TarFile. addfile(* tarinfo fileobj = None *)

    • TarInfo对象* tarinfo 添加到存档中。如果给出 fileobj *,它应该是binary file,并且从中读取tarinfo.size个字节并将其添加到存档中。您可以直接创建TarInfo对象,也可以使用gettarinfo()创建对象。
  • TarFile. gettarinfo(* name = None arcname = None fileobj = None *)

    • 根据现有文件的os.stat()的结果或等效结果创建一个TarInfo对象。该文件以* name *命名,或指定为file object * fileobj *和文件 Descriptors。 * name 可能是path-like object。如果已给定,则 arcname 指定存档中文件的替代名称,否则,该名称取自 fileobj name属性或 name *参数。名称应为文本字符串。

您可以先修改TarInfo的某些属性,然后再使用addfile()添加它。如果文件对象不是位于文件开头的普通文件对象,则可能需要修改诸如size的属性。诸如GzipFile之类的对象就是这种情况。 name也可以被修改,在这种情况下,* arcname *可以是虚拟字符串。

在版本 3.6 中更改:* name *参数接受path-like object

  • TarFile. close ( )

    • 关闭TarFile。在写入模式下,两个结尾为零的块将添加到归档中。
  • TarFile. pax_headers

    • 包含 pax 全局 Headers 的键/值对的字典。

TarInfo Objects

TarInfo对象代表TarFile中的一个成员。除了存储文件的所有必需属性(如文件类型,大小,时间,权限,所有者等)之外,它还提供了一些有用的方法来确定其类型。它不包含文件本身的数据。

TarInfo对象是由TarFile的方法getmember()getmembers()gettarinfo()返回的。

    • class * tarfile. TarInfo(* name =“” *)
    • classmethod * TarInfo. frombuf(* buf encoding errors *)
    • 从字符串缓冲区* buf *创建并返回TarInfo对象。

如果缓冲区无效,则引发HeaderError

  • 类方法 TarInfo. fromtarfile(* tarfile *)

    • TarFile对象* tarfile *中读取下一个成员,并将其作为TarInfo对象返回。
  • TarInfo. tobuf(* format = DEFAULT_FORMAT encoding = ENCODING errors ='surrogateescape'*)

    • TarInfo对象创建一个字符串缓冲区。有关参数的信息,请参见TarFile类的构造函数。

在版本 3.2 中更改:使用'surrogateescape'作为* errors *参数的默认值。

TarInfo对象具有以下公共数据属性:

  • TarInfo. name

    • 存档成员的名称。
  • TarInfo. size

    • 大小(以字节为单位)。
  • TarInfo. mtime

    • 上次修改时间。
  • TarInfo. mode

    • Permission bits.
  • TarInfo. type

    • 文件类型。 * type *通常是以下常量之一:REGTYPEAREGTYPELNKTYPESYMTYPEDIRTYPEFIFOTYPECONTTYPECHRTYPEBLKTYPEGNUTYPE_SPARSE。若要更方便地确定TarInfo对象的类型,请使用下面的is*()方法。
  • TarInfo. linkname

    • 目标文件名的名称,仅存在于LNKTYPESYMTYPE类型的TarInfo个对象中。
  • TarInfo. uid

    • 最初存储此成员的用户的用户 ID。
  • TarInfo. gid

    • 最初存储此成员的用户的组 ID。
  • TarInfo. uname

    • User name.
  • TarInfo. gname

    • Group name.
  • TarInfo. pax_headers

    • 包含关联的 pax 扩展 Headers 的键/值对的字典。

TarInfo对象还提供了一些方便的查询方法:

  • TarInfo. isfile ( )

    • 如果Tarinfo对象是常规文件,则返回True
  • TarInfo. isreg ( )

  • TarInfo. isdir ( )

    • 如果它是目录,则返回True
  • TarInfo. issym ( )

    • 如果它是符号链接,则返回True
  • TarInfo. islnk ( )

    • 如果是硬链接,则返回True
  • TarInfo. ischr ( )

    • 如果它是字符设备,则返回True
  • TarInfo. isblk ( )

    • 如果它是块设备,则返回True
  • TarInfo. isfifo ( )

    • 如果是 FIFO,则返回True
  • TarInfo. isdev ( )

    • 如果它是字符设备,块设备或 FIFO 之一,则返回True

Command-Line Interface

3.4 版的新Function。

tarfile模块提供了一个简单的命令行界面,可与 tar 存档进行交互。

如果要创建新的 tar 归档文件,请在-c选项后指定其名称,然后列出应包含的文件名:

$ python -m tarfile -c monty.tar  spam.txt eggs.txt

传递目录也是可以的:

$ python -m tarfile -c monty.tar life-of-brian_1979/

如果要将 tar 归档文件解压缩到当前目录,请使用-e选项:

$ python -m tarfile -e monty.tar

您还可以pass传递目录名称来将 tar 归档文件提取到另一个目录中:

$ python -m tarfile -e monty.tar  other-dir/

有关 tar 存档中文件的列表,请使用-l选项:

$ python -m tarfile -l monty.tar

Command-line options

  • -l <tarfile>

  • --list <tarfile>

    • 在 tarfile 中列出文件。
  • -c <tarfile> <source1> ... <sourceN>

  • --create <tarfile> <source1> ... <sourceN>

    • 从源文件创建 tarfile。
  • -e <tarfile> [<output_dir>]

  • --extract <tarfile> [<output_dir>]

    • 如果未指定* output_dir *,则将 tarfile 提取到当前目录中。
  • -t <tarfile>

  • --test <tarfile>

    • 测试 tarfile 是否有效。
  • -v `,` `--verbose`

    • Verbose output.

Examples

如何将整个 tar 归档文件提取到当前工作目录:

import tarfile
tar = tarfile.open("sample.tar.gz")
tar.extractall()
tar.close()

如何使用生成器函数而不是列表使用TarFile.extractall()提取 tar 存档的子集:

import os
import tarfile

def py_files(members):
    for tarinfo in members:
        if os.path.splitext(tarinfo.name)[1] == ".py":
            yield tarinfo

tar = tarfile.open("sample.tar.gz")
tar.extractall(members=py_files(tar))
tar.close()

如何从文件名列表创建未压缩的 tar 存档:

import tarfile
tar = tarfile.open("sample.tar", "w")
for name in ["foo", "bar", "quux"]:
    tar.add(name)
tar.close()

使用with语句的相同示例:

import tarfile
with tarfile.open("sample.tar", "w") as tar:
    for name in ["foo", "bar", "quux"]:
        tar.add(name)

如何读取 gzip 压缩的 tar 归档文件并显示一些成员信息:

import tarfile
tar = tarfile.open("sample.tar.gz", "r:gz")
for tarinfo in tar:
    print(tarinfo.name, "is", tarinfo.size, "bytes in size and is ", end="")
    if tarinfo.isreg():
        print("a regular file.")
    elif tarinfo.isdir():
        print("a directory.")
    else:
        print("something else.")
tar.close()

如何使用TarFile.add()中的* filter *参数创建 Files 并重置用户信息:

import tarfile
def reset(tarinfo):
    tarinfo.uid = tarinfo.gid = 0
    tarinfo.uname = tarinfo.gname = "root"
    return tarinfo
tar = tarfile.open("sample.tar.gz", "w:gz")
tar.add("foo", filter=reset)
tar.close()

支持的 tar 格式

tarfile模块可以创建三种 tar 格式:

  • POSIX.1-1988 ustar 格式(USTAR_FORMAT)。它支持的文件名最大长度为 256 个字符,而链接名的最大长度为 100 个字符。最大文件大小为 8 GiB。这是一种古老且有限但受广泛支持的格式。

  • GNU tar 格式(GNU_FORMAT)。它支持长文件名和链接名,大于 8 GiB 的文件和稀疏文件。它是 GNU/Linux 系统上的事实上的标准。 tarfile完全支持长名称的 GNU tar 扩展,稀疏文件支持为只读。

  • POSIX.1-2001 pax 格式(PAX_FORMAT)。这是最灵活的格式,几乎没有限制。它支持长文件名和链接名,大文件,并以可移植的方式存储路径名。包括 GNU tar,bsdtar/libarchive 和 star 在内的现代 tar 实现完全支持扩展的* pax Function;某些旧的或未维护的库可能不会,但是应该将 pax 存档视为通用支持的 ustar *格式。这是新 Files 的当前默认格式。

它使用额外的 Headers 扩展了现有的* ustar 格式,以存储否则无法存储的信息。 paxHeaders 有两种类型:扩展 Headers 仅影响后续文件 Headers,全局 Headers 对完整存档有效,并影响所有后续文件。出于可移植性原因,paxHeaders 中的所有数据都以 UTF-8 *编码。

可以读取但无法创建的 tar 格式还有更多变体:

  • 古老的 V7 格式。这是 Unix Seventh Edition 中的第一种 tar 格式,仅存储常规文件和目录。名称不得超过 100 个字符,没有用户/组名称信息。对于具有非 ASCII 字符的字段,某些 Files 文件的 Headers 校验和计算错误。

  • SunOS tar 扩展格式。此格式是 POSIX.1-2001 pax 格式的变体,但不兼容。

Unicode issues

tar 格式最初是为了在磁带驱动器上进行备份而设计的,其主要重点是保留文件系统信息。如今,tarFiles 通常用于文件分发和pass网络交换 Files。原始格式(这是所有其他格式的基础)的一个问题是,没有支持不同字符编码的概念。例如,如果在* UTF-8 系统上创建的普通 tar 归档文件包含非 ASCII 字符,则无法在 Latin-1 系统上正确读取。文本元数据(如文件名,链接名,用户/组名)将显示为已损坏。不幸的是,没有办法自动检测 Files 的编码。 pax 格式旨在解决此问题。它使用通用字符编码 UTF-8 *存储非 ASCII 元数据。

tarfile中字符转换的详细信息由TarFile类的* encoding errors *关键字参数控制。

  • encoding 定义用于存档中元数据的字符编码。默认值为sys.getfilesystemencoding()'ascii'作为后备。根据是读取还是写入存档,必须对元数据进行解码或编码。如果未正确设置 encoding *,此转换可能会失败。

  • errors *参数定义如何对待无法转换的字符。 Error Handlers部分中列出了可能的值。默认方案是'surrogateescape',Python 也将其用于其文件系统调用,请参见文件名,命令行参数和环境变量

对于PAX_FORMAT存档(默认),通常不需要* encoding ,因为所有元数据都使用 UTF-8 *存储。 * encoding *仅在少数情况下使用,当二进制 paxHeaders 被解码或存储带有代理字符的字符串时。