"shutil" --- 高阶文件操作
*************************

**原始碼：**Lib/shutil.py

======================================================================

"shutil" 模块提供了一系列对文件和文件集合的高阶操作。 特别是提供了一些
支持文件拷贝和删除的函数。 对于单个文件的操作，请参阅 "os" 模块。

警告:

  即便是高阶文件拷贝函数 ("shutil.copy()", "shutil.copy2()") 也无法拷
  贝所有的文件元数据。在 POSIX 平台上，这意味着将丢失文件所有者和组以
  及 ACL 数据。 在 Mac OS 上，资源钩子和其他元数据不被使用。 这意味着
  将丢失这些资源并且文件类型和创建者代码将不正确。 在 Windows 上，将不
  会拷贝文件所有者、ACL 和替代数据流。


目录和文件操作
==============

shutil.copyfileobj(fsrc, fdst[, length])

   将文件类对象 *fsrc* 的内容拷贝到文件类对象 *fdst*。 整数值 *length*
   如果给出则为缓冲区大小。 特别地， *length* 为负值表示拷贝数据时不对
   源数据进行分块循环处理；默认情况下会分块读取数据以避免不受控制的内
   存消耗。 请注意如果 *fsrc* 对象的当前文件位置不为 0，则只有从当前文
   件位置到文件末尾的内容会被拷贝。

shutil.copyfile(src, dst, *, follow_symlinks=True)

   将名为 *src* 的文件的内容（不包括元数据）拷贝到名为 *dst* 的文件并
   以尽可能高效的方式返回 *dst*。 *src* 和 *dst* 均为路径类对象或以字
   符串形式给出的路径名。

   *dst* 必须是完整的目标文件名；对于接受目标目录路径的拷贝请参见
   "copy()"。 如果 *src* 和 *dst* 指定了同一个文件，则将引发
   "SameFileError"。

   目标位置必须是可写的；否则将引发 "OSError" 异常。 如果 *dst* 已经存
   在，它将被替换。 特殊文件如字符或块设备以及管道无法用此函数来拷贝。

   如果 *follow_symlinks* 为假值且 *src* 为符号链接，则将创建一个新的
   符号链接而不是拷贝 *src* 所指向的文件。

   引发一个 审计事件 "shutil.copyfile" 附带参数 "src", "dst"。

   3.3 版更變: 曾经是引发 "IOError" 而不是 "OSError"。 增加了
   *follow_symlinks* 参数。 现在是返回 *dst*。

   3.4 版更變: 引发 "SameFileError" 而不是 "Error"。 由于前者是后者的
   子类，此改变是向后兼容的。

   3.8 版更變: 可能会在内部使用平台专属的快速拷贝系统调用以更高效地拷
   贝文件。 参见 依赖于具体平台的高效拷贝操作 一节。

exception shutil.SameFileError

   此异常会在 "copyfile()" 中的源和目标为同一文件时被引发。

   3.4 版新加入.

shutil.copymode(src, dst, *, follow_symlinks=True)

   从 *src* 拷贝权限位到 *dst*。 文件的内容、所有者和分组将不受影响。
   *src* 和 *dst* 均为路径类对象或字符串形式的路径名。 如果
   *follow_symlinks* 为假值，并且 *src* 和 *dst* 均为符号链接，
   "copymode()" 将尝试修改 *dst* 本身的模式（而非它所指向的文件）。 此
   功能并不是在所有平台上均可用；请参阅 "copystat()" 了解详情。 如果
   "copymode()" 无法修改本机平台上的符号链接，而它被要求这样做，它将不
   做任何操作即返回。

   引发一个 审计事件 "shutil.copymode" 附带参数 "src", "dst"。

   3.3 版更變: 新增 *follow_symlinks* 引數。

shutil.copystat(src, dst, *, follow_symlinks=True)

   从 *src* 拷贝权限位、最近访问时间、最近修改时间以及旗标到 *dst*。
   在 Linux上，"copystat()" 还会在可能的情况下拷贝“扩展属性”。 文件的
   内容、所有者和分组将不受影响。 *src* 和 *dst* 均为路径类对象或字符
   串形式的路径名。

   如果 *follow_symlinks* 为假值，并且 *src* 和 *dst* 均指向符号链接，
   "copystat()" 将作用于符号链接本身而非该符号链接所指向的文件 — 从
   *src* 符号链接读取信息，并将信息写入 *dst* 符号链接。

   備註:

     并非所有平台者提供检查和修改符号链接的功能。 Python 本身可以告诉
     你哪些功能是在本机上可用的。

     * 如果 "os.chmod in os.supports_follow_symlinks" 为 "True"，则
       "copystat()" 可以修改符号链接的权限位。

     * 如果 "os.utime in os.supports_follow_symlinks" 为 "True"，则
       "copystat()" 可以修改符号链接的最近访问和修改时间。

     * 如果 "os.chflags in os.supports_follow_symlinks" 为 "True"，则
       "copystat()" 可以修改符号链接的旗标。 ("os.chflags" 不是在所有
       平台上均可用。)

     在此功能部分或全部不可用的平台上，当被要求修改一个符号链接时，
     "copystat()" 将尽量拷贝所有内容。 "copystat()" 一定不会返回失败信
     息。更多資訊請見 "os.supports_follow_symlinks"。

   引发一个 审计事件 "shutil.copystat" 附带参数 "src", "dst"。

   3.3 版更變: 添加了 *follow_symlinks* 参数并且支持 Linux 扩展属性。

shutil.copy(src, dst, *, follow_symlinks=True)

   将文件 *src* 拷贝到文件或目录 *dst*。 *src* 和 *dst* 应为 *路径类对
   象* 或字符串。 如果 *dst* 指定了一个目录，文件将使用 *src* 中的基准
   文件名拷贝到 *dst* 中。  如果 *dst* 指定了一个已存在的文件，它将被
   替换。 返回新创建文件所对应的路径。

   如果 *follow_symlinks* 为假值且 *src* 为符号链接，则 *dst* 也将被创
   建为符号链接。 如果 *follow_symlinks* 为真值且 *src* 为符号链接，
   *dst* 将成为 *src* 所指向的文件的一个副本。

   "copy()" 会拷贝文件数据和文件的权限模式 (参见 "os.chmod()")。 其他
   元数据，例如文件的创建和修改时间不会被保留。 要保留所有原有的元数据
   ，请改用 "copy2()" 。

   引发一个 审计事件 "shutil.copyfile" 附带参数 "src", "dst"。

   引发一个 审计事件 "shutil.copymode" 附带参数 "src", "dst"。

   3.3 版更變: 添加了 *follow_symlinks* 参数。 现在会返回新创建文件的
   路径。

   3.8 版更變: 可能会在内部使用平台专属的快速拷贝系统调用以更高效地拷
   贝文件。 参见 依赖于具体平台的高效拷贝操作 一节。

shutil.copy2(src, dst, *, follow_symlinks=True)

   类似于 "copy()"，区别在于 "copy2()" 还会尝试保留文件的元数据。

   When *follow_symlinks* is false, and *src* is a symbolic link,
   "copy2()" attempts to copy all metadata from the *src* symbolic
   link to the newly created *dst* symbolic link. However, this
   functionality is not available on all platforms. On platforms where
   some or all of this functionality is unavailable, "copy2()" will
   preserve all the metadata it can; "copy2()" never raises an
   exception because it cannot preserve file metadata.

   "copy2()" 会使用 "copystat()" 来拷贝文件元数据。 请参阅
   "copystat()" 了解有关修改符号链接元数据的平台支持的更多信息。

   引发一个 审计事件 "shutil.copyfile" 附带参数 "src", "dst"。

   引发一个 审计事件 "shutil.copystat" 附带参数 "src", "dst"。

   3.3 版更變: 添加了 *follow_symlinks* 参数，还会尝试拷贝扩展文件系统
   属性（目前仅限 Linux）。 现在会返回新创建文件的路径。

   3.8 版更變: 可能会在内部使用平台专属的快速拷贝系统调用以更高效地拷
   贝文件。 参见 依赖于具体平台的高效拷贝操作 一节。

shutil.ignore_patterns(*patterns)

   这个工厂函数会创建一个函数，它可被用作 "copytree()" 的 *ignore* 可
   调用对象参数，以忽略那些匹配所提供的 glob 风格的 *patterns* 之一的
   文件和目录。 参见以下示例。

shutil.copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False, dirs_exist_ok=False)

   递归地将以 *src* 为根起点的整个目录树拷贝到名为 *dst* 的目录并返回
   目标目录。 所需的包含 *dst* 的中间目录在默认情况下也将被创建。

   目录的权限和时间会通过 "copystat()" 来拷贝，单个文件则会使用
   "copy2()" 来拷贝。

   如果 *symlinks* 为真值，源目录树中的符号链接会在新目录树中表示为符
   号链接，并且原链接的元数据在平台允许的情况下也会被拷贝；如果为假值
   或省略，则会将被链接文件的内容和元数据拷贝到新目录树。

   当 *symlinks* 为假值时，如果符号链接所指向的文件不存在，则会在拷贝
   进程的末尾将一个异常添加到 "Error" 异常中的错误列表。 如果你希望屏
   蔽此异常那就将可选的 *ignore_dangling_symlinks* 旗标设为真值。 请注
   意此选项在不支持 "os.symlink()" 的平台上将不起作用。

   如果给出了 *ignore*，它必须是一个可调用对象，该对象将接受
   "copytree()" 所访问的目录以及 "os.listdir()" 所返回的目录内容列表作
   为其参数。 由于 "copytree()" 是递归地被调用的，*ignore* 可调用对象
   对于每个被拷贝目录都将被调用一次。 该可调用对象必须返回一个相对于当
   前目录的目录和文件名序列（即其第二个参数的子集）；随后这些名称将在
   拷贝进程中被忽略。 "ignore_patterns()" 可被用于创建这种基于 glob 风
   格模式来忽略特定名称的可调用对象。

   如果发生了（一个或多个）异常，将引发一个附带原因列表的 "Error"。

   如果给出了 *copy_function*，它必须是一个将被用来拷贝每个文件的可调
   用对象。 它在被调用时会将源路径和目标路径作为参数传入。 默认情况下
   ，"copy2()" 将被使用，但任何支持同样签名（与 "copy()" 一致）都可以
   使用。

   如果 *dirs_exist_ok* 为（默认的）假值且 *dst* 已存在，则会引发
   "FileExistsError"。 如果 *dirs_exist_ok* 为真值，则如果拷贝操作遇到
   已存在的目录时将继续执行，并且在 *dst* 目录树中的文件将被 *src* 目
   录树中对应的文件所覆盖。

   引发一个 审计事件 "shutil.copytree" 附带参数 "src", "dst"。

   3.3 版更變: 当 *symlinks* 为假值时拷贝元数据。 现在会返回 *dst*。

   3.2 版更變: 添加了 *copy_function* 参数以允许提供定制的拷贝函数。
   添加了 *ignore_dangling_symlinks* 参数以便在 *symlinks* 为假值时屏
   蔽目标不存在的符号链接。

   3.8 版更變: 可能会在内部使用平台专属的快速拷贝系统调用以更高效地拷
   贝文件。 参见 依赖于具体平台的高效拷贝操作 一节。

   3.8 版新加入: *dirs_exist_ok* 參數。

shutil.rmtree(path, ignore_errors=False, onerror=None)

   删除一个完整的目录树；*path* 必须指向一个目录（但不能是一个目录的符
   号链接）。 如果 *ignore_errors* 为真值，删除失败导致的错误将被忽略
   ；如果为假值或是省略，此类错误将通过调用由 *onerror* 所指定的处理程
   序来处理，或者如果此参数被省略则将引发一个异常。

   備註:

     在支持必要的基于 fd 的函数的平台上，默认会使用 "rmtree()" 的可防
     御符号链接攻击的版本。 在其他平台上，"rmtree()" 较易遭受符号链接
     攻击：给定适当的时间和环境，攻击者可以操纵文件系统中的符号链接来
     删除他们在其他情况下无法访问的文件。 应用程序可以使用
     "rmtree.avoids_symlink_attacks" 函数属性来确定此类情况具体是哪一
     些。

   如果提供了 *onerror*，它必须为接受三个形参的可调用对象: *function*,
   *path* 和 *excinfo*。

   第一个形参 *function* 是引发异常的函数；它依赖于具体的平台和实现。
   第二个形参 *path* 将是传递给 *function* 的路径名。 第三个形参
   *excinfo* 将是由 "sys.exc_info()" 所返回的异常信息。 由 *onerror*
   所引发的异常将不会被捕获。

   引发一个 审计事件 "shutil.rmtree" 附带参数 "path"。

   3.3 版更變: 添加了一个防御符号链接攻击的版本，如果平台支持基于 fd
   的函数就会被使用。

   3.8 版更變: 在 Windows 上将不会再在移除连接之前删除目录连接中的内容
   。

   rmtree.avoids_symlink_attacks

      指明当前平台和实现是否提供防御符号链接攻击的 "rmtree()" 版本。
      目前它仅在平台支持基于 fd 的目录访问函数时才返回真值。

      3.3 版新加入.

shutil.move(src, dst, copy_function=copy2)

   递归地将一个文件或目录 (*src*) 移至另一位置 (*dst*) 并返回目标位置
   。

   如果目标是已存在的目录，则 *src* 会被移至该目录下。 如果目标已存在
   但不是目录，它可能会被覆盖，具体取决于 "os.rename()" 的语义。

   如果目标是在当前文件系统中，则会使用 "os.rename()"。 在其他情况下，
   *src* 将被拷贝至 *dst*，使用的函数为 *copy_function*，然后目标会被
   移除。 对于符号链接，则将在 *dst* 之下或以其本身为名称创建一个指向
   *src* 目标的新符号链接，并且 *src* 将被移除。

   如果给出了 *copy_function*，则它必须为接受两个参数 *src* 和 *dst*
   的可调用对象，并将在 "os.rename()" 无法使用时被用来将 *src* 拷贝到
   *dst*。 如果源是一个目录，则会调用 "copytree()"，并向它传入
   "copy_function()"。 默认的 *copy_function* 是 "copy2()"。 使用
   "copy()" 作为 *copy_function* 允许在无法附带拷贝元数据时让移动操作
   成功执行，但其代价是不拷贝任何元数据。

   引发一个 审计事件 "shutil.move" 附带参数 "src", "dst"。

   3.3 版更變: 为异类文件系统添加了显式的符号链接处理，以便使它适应
   GNU 的 **mv** 的行为。 现在会返回 *dst*。

   3.5 版更變: 新增 *copy_function* 關鍵字引數。

   3.8 版更變: 可能会在内部使用平台专属的快速拷贝系统调用以更高效地拷
   贝文件。 参见 依赖于具体平台的高效拷贝操作 一节。

   3.9 版更變: 接受一个 *path-like object* 作为 *src* 和 *dst*。

shutil.disk_usage(path)

   返回给定路径的磁盘使用统计数据，形式为一个 *named tuple*，其中包含
   *total*, *used* 和 *free* 属性，分别表示总计、已使用和未使用空间的
   字节数。 *path* 可以是一个文件或是一个目录。

   3.3 版新加入.

   3.8 版更變: 在 Windows 上，*path* 现在可以是一个文件或目录。

   適用：Unix、Windows。

shutil.chown(path, user=None, group=None)

   修改给定 *path* 的所有者 *user* 和/或 *group*。

   *user* 可以是一个系统用户名或 uid；*group* 同样如此。 要求至少有一
   个参数。

   另请参阅下层的函数 "os.chown()"。

   引发一个 审计事件 "shutil.chown" 附带参数 "path", "user", "group"。

   適用：Unix。

   3.3 版新加入.

shutil.which(cmd, mode=os.F_OK | os.X_OK, path=None)

   返回当给定的 *cmd* 被调用时将要运行的可执行文件的路径。 如果没有
   *cmd* 会被调用则返回 "None"。

   *mode* 是一个传递给 "os.access()" 的权限掩码，在默认情况下将确定文
   件是否存在并且为可执行文件。

   当未指定 *path* 时，将会使用 "os.environ()" 的结果，返回 "PATH" 的
   值或回退为 "os.defpath"。

   在 Windows 上当前目录总是会被添加为 *path* 的第一项，无论你是否使用
   默认值或提供你自己的路径，这是命令行终端在查找可执行文件时所采用的
   行为方式。 此外，当在 *path* 中查找 *cmd* 时，还会检查 "PATHEXT" 环
   境变量。 例如，如果你调用 "shutil.which("python")"，"which()" 将搜
   索 "PATHEXT" 来确定它要在 *path* 目录中查找 "python.exe"。 例如，在
   Windows 上:

      >>> shutil.which("python")
      'C:\\Python33\\python.EXE'

   3.3 版新加入.

   3.8 版更變: 现在可以接受 "bytes" 类型。 如果 *cmd* 的类型为 "bytes"
   ，结果的类型也将为 "bytes"。

exception shutil.Error

   此异常会收集在多文件操作期间所引发的异常。 对于 "copytree()"，此异
   常参数将是一个由三元组 (*srcname*, *dstname*, *exception*) 构成的列
   表。


依赖于具体平台的高效拷贝操作
----------------------------

从 Python 3.8 开始，所有涉及文件拷贝的函数 ("copyfile()", "copy()",
"copy2()", "copytree()" 以及 "move()") 将会使用平台专属的 "fast-copy"
系统调用以便更高效地拷贝文件 (参见 bpo-33671)。 "fast-copy" 意味着拷贝
操作将发生于内核之中，避免像在 ""outfd.write(infd.read())"" 中那样使用
Python 用户空间的缓冲区。

在 macOS 上将会使用 fcopyfile 来拷贝文件内容（不含元数据）。

在 Linux 上将会使用 "os.sendfile()"。

在 Windows 上 "shutil.copyfile()" 将会使用更大的默认缓冲区（1 MiB 而非
64 KiB）并且会使用基于 "memoryview()" 的 "shutil.copyfileobj()" 变种形
式。

如果快速拷贝操作失败并且没有数据被写入目标文件，则 shutil 将在内部静默
地回退到使用效率较低的 "copyfileobj()" 函数。

3.8 版更變.


copytree 示例
-------------

一个使用 "ignore_patterns()" 辅助函数的例子:

   from shutil import copytree, ignore_patterns

   copytree(source, destination, ignore=ignore_patterns('*.pyc', 'tmp*'))

这将会拷贝除 ".pyc" 文件和以 "tmp" 打头的文件或目录以外的所有条目.

另一个使用 *ignore* 参数来添加记录调用的例子:

   from shutil import copytree
   import logging

   def _logpath(path, names):
       logging.info('Working in %s', path)
       return []   # nothing will be ignored

   copytree(source, destination, ignore=_logpath)


rmtree 範例
-----------

这个例子演示了如何在 Windows 上删除一个目录树，其中部分文件设置了只读
属性位。 它会使用 onerror 回调函数来清除只读属性位并再次尝试删除。 任
何后续的失败都将被传播。

   import os, stat
   import shutil

   def remove_readonly(func, path, _):
       "Clear the readonly bit and reattempt the removal"
       os.chmod(path, stat.S_IWRITE)
       func(path)

   shutil.rmtree(directory, onerror=remove_readonly)


归档操作
========

3.2 版新加入.

3.5 版更變: 新增 *xztar* 格式的支援。

本模块也提供了用于创建和读取压缩和归档文件的高层级工具。 它们依赖于
"zipfile" 和 "tarfile" 模块。

shutil.make_archive(base_name, format[, root_dir[, base_dir[, verbose[, dry_run[, owner[, group[, logger]]]]]]])

   创建一个归档文件（例如 zip 或 tar）并返回其名称。

   *base_name* 是要创建的文件名称，包括路径，去除任何特定格式的扩展名
   。 *format* 是归档格式：为 "zip" (如果 "zlib" 模块可用), "tar",
   "gztar" (如果 "zlib" 模块可用), "bztar" (如果 "bz2" 模块可用) 或
   "xztar" (如果 "lzma" 模块可用) 中的一个。

   *root_dir* 是一个目录，它将作为归档文件的根目录，归档中的所有路径都
   将是它的相对路径；例如，我们通常会在创建归档之前用 chdir 命令切换到
   *root_dir*。

   *base_dir* 是我们要执行归档的起始目录；也就是说 *base_dir* 将成为归
   档中所有文件和目录共有的路径前缀。 *base_dir* 必须相对于 *root_dir*
   给出。 请参阅 使用 base_dir 的归档程序示例 了解如何同时使用
   *base_dir* 和 *root_dir*。

   *root_dir* 和 *base_dir* 默认均为当前目录。

   如果 *dry_run* 为真值，则不会创建归档文件，但将要被执行的操作会被记
   录到 *logger*。

   *owner* 和 *group* 将在创建 tar 归档文件时被使用。 默认会使用当前的
   所有者和分组。

   *logger* 必须是一个兼容 **PEP 282** 的对象，通常为 "logging.Logger"
   的实例。

   *verbose* 参数已不再使用并进入弃用状态。

   引发一个 审计事件 "shutil.make_archive" 并附带参数 "base_name",
   "format", "root_dir", "base_dir"。

   備註:

     This function is not thread-safe when custom archivers registered
     with "register_archive_format()" are used.  In this case it
     temporarily changes the current working directory of the process
     to perform archiving.

   3.8 版更變: 现在对于通过 "format="tar"" 创建的归档文件将使用新式的
   pax (POSIX.1-2001) 格式而非旧式的 GNU 格式。

   3.10.6 版更變: This function is now made thread-safe during
   creation of standard ".zip" and tar archives.

shutil.get_archive_formats()

   返回支持的归档格式列表。 所返回序列中的每个元素为一个元组 "(name,
   description)"。

   默认情况下 "shutil" 提供以下格式:

   * *zip*: ZIP 文件（如果 "zlib" 模块可用）。

   * *tar*: 未压缩的 tar 文件。 对于新归档文件将使用 POSIX.1-2001 pax
     格式。

   * *gztar*: gzip 压缩的 tar 文件（如果 "zlib" 模块可用）。

   * *bztar*: bzip2 压缩的 tar 文件（如果 "bz2" 模块可用）。

   * *xztar*: xz 压缩的 tar 文件（如果 "lzma" 模块可用）。

   你可以通过使用 "register_archive_format()" 注册新的格式或为任何现有
   格式提供你自己的归档器。

shutil.register_archive_format(name, function[, extra_args[, description]])

   为 *name* 格式注册一个归档器。

   *function* 是将被用来解包归档文件的可调用对象。 该可调用对象将接收
   要创建文件的 *base_name*，再加上要归档内容的 *base_dir* (其默认值为
   "os.curdir")。 更多参数会被作为关键字参数传入: *owner*, *group*,
   *dry_run* 和 *logger* (与向 "make_archive()" 传入的参数一致)。

   如果给出了 *extra_args*，则其应为一个 "(name, value)" 对的序列，将
   在归档器可调用对象被使用时作为附加的关键字参数。

   *description* 由 "get_archive_formats()" 使用，它将返回归档器的列表
   。 默认值为一个空字符串。

shutil.unregister_archive_format(name)

   从支持的格式中移除归档格式 *name*。

shutil.unpack_archive(filename[, extract_dir[, format[, filter]]])

   解包一个归档文件。 *filename* 是归档文件的完整路径。

   *extract_dir* 是归档文件解包的目标目录名称。 如果未提供，则将使用当
   前工作目录。

   *format* 是归档格式：应为 "zip", "tar", "gztar", "bztar" 或 "xztar"
   之一。 或者任何通过 "register_unpack_format()" 注册的其他格式。 如
   果未提供，"unpack_archive()" 将使用归档文件的扩展名来检查是否注册了
   对应于该扩展名的解包器。 在未找到任何解包器的情况下，将引发
   "ValueError"。

   The keyword-only *filter* argument, which was added in Python
   3.10.12, is passed to the underlying unpacking function. For zip
   files, *filter* is not accepted. For tar files, it is recommended
   to set it to "'data'", unless using features specific to tar and
   UNIX-like filesystems. (See Extraction filters for details.) The
   "'data'" filter will become the default for tar files in Python
   3.14.

   引发一个 审计事件 "shutil.unpack_archive" 附带参数 "filename",
   "extract_dir", "format"。

   警告:

     绝不要未经预先检验就从不可靠的源中提取归档文件。 这样有可能会在
     *extract_dir* 参数所指定的路径之外创建文件，例如某些成员具有以
     "/" 打头的绝对路径文件名或是以两个点号 ".." 打头的文件名。

   3.7 版更變: 接受一个 *path-like object* 作为 *filename* 和
   *extract_dir*。

   3.10.12 版更變: Added the *filter* argument.

shutil.register_unpack_format(name, extensions, function[, extra_args[, description]])

   注册一个解包格式。 *name* 为格式名称而 *extensions* 为对应于该格式
   的扩展名列表，例如 Zip 文件的扩展名为 ".zip"。

   *function* is the callable that will be used to unpack archives.
   The callable will receive:

   * the path of the archive, as a positional argument;

   * the directory the archive must be extracted to, as a positional
     argument;

   * possibly a *filter* keyword argument, if it was given to
     "unpack_archive()";

   * additional keyword arguments, specified by *extra_args* as a
     sequence of "(name, value)" tuples.

   可以提供 *description* 来描述该格式，它将被 "get_unpack_formats()"
   返回。

shutil.unregister_unpack_format(name)

   撤销注册一个解包格式。 *name* 为格式的名称。

shutil.get_unpack_formats()

   返回所有已注册的解包格式列表。 所返回序列中的每个元素为一个元组
   "(name, extensions, description)"。

   默认情况下 "shutil" 提供以下格式:

   * *zip*: ZIP 文件（只有在相应模块可用时才能解包压缩文件）。

   * *tar*: 未压缩的 tar 文件。

   * *gztar*: gzip 压缩的 tar 文件（如果 "zlib" 模块可用）。

   * *bztar*: bzip2 压缩的 tar 文件（如果 "bz2" 模块可用）。

   * *xztar*: xz 压缩的 tar 文件（如果 "lzma" 模块可用）。

   你可以通过使用 "register_unpack_format()" 注册新的格式或为任何现有
   格式提供你自己的解包器。


归档程序示例
------------

在这个示例中，我们创建了一个 gzip 压缩的 tar 归档文件，其中包含用户的
".ssh" 目录下的所有文件:

   >>> from shutil import make_archive
   >>> import os
   >>> archive_name = os.path.expanduser(os.path.join('~', 'myarchive'))
   >>> root_dir = os.path.expanduser(os.path.join('~', '.ssh'))
   >>> make_archive(archive_name, 'gztar', root_dir)
   '/Users/tarek/myarchive.tar.gz'

结果归档文件中包含有:

   $ tar -tzvf /Users/tarek/myarchive.tar.gz
   drwx------ tarek/staff       0 2010-02-01 16:23:40 ./
   -rw-r--r-- tarek/staff     609 2008-06-09 13:26:54 ./authorized_keys
   -rwxr-xr-x tarek/staff      65 2008-06-09 13:26:54 ./config
   -rwx------ tarek/staff     668 2008-06-09 13:26:54 ./id_dsa
   -rwxr-xr-x tarek/staff     609 2008-06-09 13:26:54 ./id_dsa.pub
   -rw------- tarek/staff    1675 2008-06-09 13:26:54 ./id_rsa
   -rw-r--r-- tarek/staff     397 2008-06-09 13:26:54 ./id_rsa.pub
   -rw-r--r-- tarek/staff   37192 2010-02-06 18:23:10 ./known_hosts


使用 *base_dir* 的归档程序示例
------------------------------

在这个例子中，与 上面的例子 类似，我们演示了如何使用 "make_archive()"
，但这次是使用 *base_dir*。 我们现在具有如下的目录结构:

   $ tree tmp
   tmp
   └── root
       └── structure
           ├── content
               └── please_add.txt
           └── do_not_add.txt

在最终的归档中，应当会包括 "please_add.txt"，但不应当包括
"do_not_add.txt"。 因此我们使用以下代码:

   >>> from shutil import make_archive
   >>> import os
   >>> archive_name = os.path.expanduser(os.path.join('~', 'myarchive'))
   >>> make_archive(
   ...     archive_name,
   ...     'tar',
   ...     root_dir='tmp/root',
   ...     base_dir='structure/content',
   ... )
   '/Users/tarek/my_archive.tar'

列出结果归档中的文件我们将会得到:

   $ python -m tarfile -l /Users/tarek/myarchive.tar
   structure/content/
   structure/content/please_add.txt


查询输出终端的尺寸
==================

shutil.get_terminal_size(fallback=(columns, lines))

   获取终端窗口的尺寸。

   对于两个维度中的每一个，会分别检查环境变量 "COLUMNS" 和 "LINES"。
   如果定义了这些变量并且其值为正整数，则将使用这些值。

   如果未定义 "COLUMNS" 或 "LINES"，这是通常的情况，则连接到
   "sys.__stdout__" 的终端将通过发起调用 "os.get_terminal_size()" 被查
   询。

   如果由于系统不支持查询，或是由于我们未连接到某个终端而导致查询终端
   尺寸不成功，则会使用在 "fallback" 形参中给出的值。 "fallback" 默认
   为 "(80, 24)"，这是许多终端模拟器所使用的默认尺寸。

   返回的值是一个 "os.terminal_size" 类型的具名元组。

   另请参阅: The Single UNIX Specification, Version 2, Other
   Environment Variables.

   3.3 版新加入.
