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,则只复制从当前文件位置到文件末尾的内容。

copyfileobj() 保证在复制完成后目标流已被刷新。如果您想在复制操作完成后从目标读取(例如,读取从 HTTP 流复制的临时文件的内容),则必须确保在尝试读取目标文件之前已在文件类对象上调用了 flush()close()

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

以最有效的方式将名为 src 的文件的内容(不含元数据)复制到名为 dst 的文件,并返回 dstsrcdst路径类对象 或以字符串形式给出的路径名。

dst 必须是完整的目标文件名;对于接受目标目录路径的复制操作,请参阅 copy()。如果 srcdst 指定同一文件,则会引发 SameFileError

目标位置必须可写入;否则,将引发 OSError 异常。如果 dst 已存在,它将被替换。字符或块设备以及管道等特殊文件不能使用此函数复制。

如果 follow_symlinks 为 false 且 src 是符号链接,则会创建一个新的符号链接,而不是复制 src 指向的文件。

引发带有参数 srcdst审计事件 shutil.copyfile

3.3 版本中已更改: 以前引发 IOError 而不是 OSError。添加了 follow_symlinks 参数。现在返回 dst

3.4 版本中已更改: 引发 SameFileError 而不是 Error。由于前者是后者的子类,此更改是向后兼容的。

3.8 版本中已更改: 为了更有效地复制文件,内部可能会使用平台特定的快速复制系统调用。请参阅 平台相关的高效复制操作 部分。

exception shutil.SpecialFileError

copyfile()copytree() 尝试复制命名管道时,会引发此异常。

2.7 版本新增。

exception shutil.SameFileError

如果 copyfile() 中的源和目标是同一文件,则会引发此异常。

在 3.4 版本加入。

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

将权限位从 src 复制到 dst。文件内容、所有者和组不受影响。srcdst路径类对象 或以字符串形式给出的路径名。如果 follow_symlinks 为 false,并且 srcdst 都是符号链接,copymode() 将尝试修改 dst 本身的模式(而不是它指向的文件)。此功能并非在每个平台上都可用;请参阅 copystat() 获取更多信息。如果 copymode() 无法在本地平台上修改符号链接,并且被要求这样做,它将不执行任何操作并返回。

引发带有参数 srcdst审计事件 shutil.copymode

3.3 版本中已更改: 添加了 follow_symlinks 参数。

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

复制 src 的权限位、最后访问时间、最后修改时间和标志到 dst。在 Linux 上,copystat() 还会尽可能地复制“扩展属性”。文件内容、所有者和组不受影响。srcdst路径类对象 或以字符串形式给出的路径名。

如果 follow_symlinks 为 false,并且 srcdst 都指向符号链接,copystat() 将操作符号链接本身,而不是符号链接指向的文件——从 src 符号链接读取信息,并将信息写入 dst 符号链接。

备注

并非所有平台都提供检查和修改符号链接的功能。Python 本身可以告诉您本地可用哪些功能。

  • 如果 os.chmod in os.supports_follow_symlinksTruecopystat() 可以修改符号链接的权限位。

  • 如果 os.utime in os.supports_follow_symlinksTruecopystat() 可以修改符号链接的最后访问时间和修改时间。

  • 如果 os.chflags in os.supports_follow_symlinksTruecopystat() 可以修改符号链接的标志。(os.chflags 并非在所有平台上都可用。)

在某些或所有此功能不可用的平台上,当被要求修改符号链接时,copystat() 将复制所有它能复制的内容。copystat() 绝不会返回失败。

请参阅 os.supports_follow_symlinks 获取更多信息。

引发带有参数 srcdst审计事件 shutil.copystat

3.3 版本中已更改: 添加了 follow_symlinks 参数并支持 Linux 扩展属性。

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

将文件 src 复制到文件或目录 dstsrcdst 应为 路径类对象 或字符串。如果 dst 指定一个目录,文件将使用 src 的基本文件名复制到 dst 中。如果 dst 指定的文件已经存在,它将被替换。返回新创建文件的路径。

如果 follow_symlinks 为 false 且 src 是符号链接,则 dst 将被创建为符号链接。如果 follow_symlinks 为 true 且 src 是符号链接,则 dst 将是 src 指向的文件的副本。

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

引发带有参数 srcdst审计事件 shutil.copyfile

引发带有参数 srcdst审计事件 shutil.copymode

3.3 版本中已更改: 添加了 follow_symlinks 参数。现在返回新创建文件的路径。

3.8 版本中已更改: 为了更有效地复制文件,内部可能会使用平台特定的快速复制系统调用。请参阅 平台相关的高效复制操作 部分。

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

copy() 相同,只是 copy2() 也尝试保留文件元数据。

follow_symlinks 为 false 且 src 是符号链接时,copy2() 尝试将 src 符号链接的所有元数据复制到新创建的 dst 符号链接。然而,此功能并非在所有平台上都可用。在某些或所有此功能不可用的平台上,copy2() 将保留所有它能保留的元数据;copy2() 绝不会因为无法保留文件元数据而引发异常。

copy2() 使用 copystat() 复制文件元数据。请参阅 copystat() 获取有关修改符号链接元数据的平台支持的更多信息。

引发带有参数 srcdst审计事件 shutil.copyfile

引发带有参数 srcdst审计事件 shutil.copystat

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 为 true,则源树中的符号链接在新树中表示为符号链接,并且原始链接的元数据将尽可能地复制(取决于平台);如果为 false 或省略,则链接文件的内容和元数据将复制到新树中。

symlinks 为 false 时,如果符号链接指向的文件不存在,则会在复制过程结束时引发 Error 异常的错误列表中添加一个异常。如果您想抑制此异常,可以将可选的 ignore_dangling_symlinks 标志设置为 true。请注意,此选项对不支持 os.symlink() 的平台无效。

如果给定了 ignore,它必须是一个可调用对象,该对象将接收 copytree() 正在访问的目录以及其内容的列表作为参数,该列表由 os.listdir() 返回。由于 copytree() 是递归调用的,因此 ignore 可调用对象将为每个复制的目录调用一次。可调用对象必须返回一个相对于当前目录的目录和文件名的序列(即其第二个参数中的项的子集);这些名称将在复制过程中被忽略。ignore_patterns() 可用于创建这样一个可调用对象,该对象根据 glob 样式模式忽略名称。

如果发生异常,将引发带有原因列表的 Error

如果给定了 copy_function,它必须是一个可调用对象,将用于复制每个文件。它将以源路径和目标路径作为参数调用。默认情况下,使用 copy2(),但任何支持相同签名的函数(如 copy())都可以使用。

如果 dirs_exist_ok 为 false(默认值)且 dst 已存在,则会引发 FileExistsError。如果 dirs_exist_ok 为 true,则复制操作将继续(如果遇到现有目录),并且 dst 树中的文件将被 src 树中的相应文件覆盖。

引发带有参数 srcdst审计事件 shutil.copytree

3.2 版本中已更改: 添加了 copy_function 参数,以便提供自定义复制函数。添加了 ignore_dangling_symlinks 参数,以便在 symlinks 为 false 时抑制悬空符号链接错误。

3.3 版本中已更改: symlinks 为 false 时复制元数据。现在返回 dst

3.8 版本中已更改: 为了更有效地复制文件,内部可能会使用平台特定的快速复制系统调用。请参阅 平台相关的高效复制操作 部分。

3.8 版本中已更改: 添加了 dirs_exist_ok 参数。

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

删除整个目录树;path 必须指向一个目录(但不是指向目录的符号链接)。如果 ignore_errors 为 true,则忽略因删除失败而导致的错误;如果为 false 或省略,则由 onexconerror 指定的处理器处理此类错误,如果两者都省略,则将异常传播给调用方。

此函数可以支持 相对于目录描述符的路径

备注

在支持必要的基于 fd 的函数的平台上,默认使用 rmtree() 的防符号链接攻击版本。在其他平台上,rmtree() 实现容易受到符号链接攻击:在适当的时机和环境下,攻击者可以在文件系统上操纵符号链接以删除他们原本无法访问的文件。应用程序可以使用 rmtree.avoids_symlink_attacks 函数属性来确定适用哪种情况。

如果提供了 onexc,它必须是一个可调用对象,接受三个参数:functionpathexcinfo

第一个参数 function 是引发异常的函数;它取决于平台和实现。第二个参数 path 将是传递给 function 的路径名。第三个参数 excinfo 是引发的异常。onexc 引发的异常不会被捕获。

已弃用的 onerror 类似于 onexc,只是它接收的第三个参数是 sys.exc_info() 返回的元组。

参见

rmtree 示例 用于处理包含只读文件的目录树删除的示例。

引发带有参数 pathdir_fd审计事件 shutil.rmtree

3.3 版本中已更改: 添加了一个防符号链接攻击版本,如果平台支持基于 fd 的函数,则会自动使用。

3.8 版本中已更改: 在 Windows 上,在删除目录连接之前,不再删除目录连接的内容。

3.11 版本中已更改: 添加了 dir_fd 参数。

3.12 版本中已更改: 添加了 onexc 参数,弃用了 onerror

3.13 版本中已更改: rmtree() 现在忽略除顶级路径之外的所有 FileNotFoundError 异常。除 OSError 及其子类之外的异常现在总是传播给调用方。

指示当前平台和实现是否提供防符号链接攻击版本的 rmtree()。目前,这仅适用于支持基于 fd 的目录访问函数的平台。

在 3.3 版本加入。

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

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

如果 dst 是一个现有目录或指向目录的符号链接,则 src 将移动到该目录中。该目录中的目标路径不得已存在。

如果 dst 已经存在但不是目录,它可能会被覆盖,具体取决于 os.rename() 的语义。

如果目标在当前文件系统上,则使用 os.rename()。否则,src 将使用 copy_function 复制到目标,然后删除。对于符号链接,将创建一个指向 src 目标的新符号链接作为目标,并删除 src

如果给定了 copy_function,它必须是一个可调用对象,接受 src 和目标作为两个参数,如果无法使用 os.rename(),它将用于将 src 复制到目标。如果源是目录,则会调用 copytree(),并将 copy_function 传递给它。默认的 copy_functioncopy2()。使用 copy() 作为 copy_function 允许在无法复制元数据的情况下成功移动,代价是不复制任何元数据。

引发带有参数 srcdst审计事件 shutil.move

3.3 版本中已更改: 为外部文件系统添加了显式符号链接处理,从而使其适应 GNU 的 mv 的行为。现在返回 dst

3.5 版本中已更改: 添加了 copy_function 关键字参数。

3.8 版本中已更改: 为了更有效地复制文件,内部可能会使用平台特定的快速复制系统调用。请参阅 平台相关的高效复制操作 部分。

3.9 版本中已更改: srcdst 都接受 路径类对象

shutil.disk_usage(path)

返回给定路径的磁盘使用统计信息,作为具有属性 totalusedfree命名元组,它们是总空间、已用空间和可用空间的字节数。path 可以是文件或目录。

备注

在 Unix 文件系统上,path 必须指向 已挂载 文件系统分区内的路径。在这些平台上,CPython 不会尝试从未挂载的文件系统检索磁盘使用信息。

在 3.3 版本加入。

3.8 版本中已更改: 在 Windows 上,path 现在可以是文件或目录。

可用性: Unix, Windows。

shutil.chown(path, user=None, group=None, *, dir_fd=None, follow_symlinks=True)

更改给定 path 的所有者 user 和/或 group

user 可以是系统用户名或 uid;group 也是如此。至少需要一个参数。

另请参阅 os.chown(),它是底层函数。

引发带有参数 pathusergroup审计事件 shutil.chown

可用性: Unix。

在 3.3 版本加入。

3.13 版本中已更改: 添加了 dir_fdfollow_symlinks 参数。

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

返回如果调用给定 cmd 将运行的可执行文件的路径。如果没有可执行文件将被调用,则返回 None

mode 是传递给 os.access() 的权限掩码,默认情况下确定文件是否存在且可执行。

path 是一个“PATH 字符串”,指定要查找的目录,由 os.pathsep 分隔。当未指定 path 时,PATH 环境变量从 os.environ 读取,如果未设置则回退到 os.defpath

如果 cmd 包含目录组件,which() 只直接检查指定的路径,而不搜索 path 或系统 PATH 环境变量中列出的目录。

在 Windows 上,如果 mode 不包含 os.X_OK,则当前目录将添加到 path 的前面。当 mode 包含 os.X_OK 时,将查询 Windows API NeedCurrentDirectoryForExePathW 以确定是否应将当前目录添加到 path 的前面。要避免为可执行文件查询当前工作目录:设置环境变量 NoDefaultCurrentDirectoryInExePath

在 Windows 上,PATHEXT 环境变量也用于解析可能尚未包含扩展名的命令。例如,如果您调用 shutil.which("python")which() 将搜索 PATHEXT 以了解它应该在 path 目录中查找 python.exe。例如,在 Windows 上

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

cmd 是包含目录组件的路径时,这也适用

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

在 3.3 版本加入。

3.8 版本中已更改: 现在接受 bytes 类型。如果 cmd 类型是 bytes,则结果类型也是 bytes

3.12 版本中已更改: 在 Windows 上,如果 mode 包含 os.X_OK 且 WinAPI NeedCurrentDirectoryForExePathW(cmd) 为 false,则不再将当前目录添加到搜索路径前面,否则即使当前目录已在搜索路径中,也会将其添加到前面;即使 cmd 包含目录组件或以 PATHEXT 中的扩展名结尾,现在也会使用 PATHEXT;现在可以找到没有扩展名的文件名。

exception shutil.Error

此异常收集在多文件操作期间引发的异常。对于 copytree(),异常参数是 3 元组 (srcname, dstname, exception) 的列表。

平台相关的有效复制操作

从 Python 3.8 开始,所有涉及文件复制的函数(copyfile()copy()copy2()copytree()move())可能会使用平台特定的“快速复制”系统调用,以便更有效地复制文件(参见 bpo-33671)。“快速复制”意味着复制操作发生在内核内部,避免了像“outfd.write(infd.read())”那样在 Python 中使用用户空间缓冲区。

在 macOS 上,使用 fcopyfile 复制文件内容(不包括元数据)。

在 Linux 上,使用 os.copy_file_range()os.sendfile()

在 Solaris 上,使用 os.sendfile()

在 Windows 上,shutil.copyfile() 使用更大的默认缓冲区大小(1 MiB 而不是 64 KiB),并使用基于 memoryview()shutil.copyfileobj() 变体。

如果快速复制操作失败且没有数据写入目标文件,则 shutil 将静默回退到内部使用效率较低的 copyfileobj() 函数。

3.8 版本中已更改。

3.14 版本中已更改: Solaris 现在使用 os.sendfile()

3.14 版本中已更改: 在支持的 Linux 文件系统上,可以通过 os.copy_file_range() 内部使用写时复制或服务器端复制。

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 上删除目录树,其中某些文件设置了只读位。它使用 onexc 回调来清除只读位并重新尝试删除。任何后续失败都将传播。

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, onexc=remove_readonly)

归档操作

在 3.2 版本加入。

3.5 版本中已更改: 添加了对 xztar 格式的支持。

还提供了用于创建和读取压缩和归档文件的高级实用程序。它们依赖于 zipfiletarfile 模块。

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 模块可用)或“zstdtar”(如果 compression.zstd 模块可用)。

root_dir 是将作为归档根目录的目录,归档中的所有路径都将相对于它;例如,我们通常在创建归档之前 chdir 到 root_dir

base_dir 是我们开始归档的目录;即 base_dir 将是归档中所有文件和目录的共同前缀。base_dir 必须相对于 root_dir 给出。有关如何将 base_dirroot_dir 一起使用,请参阅 带有 base_dir 的归档示例

root_dirbase_dir 都默认为当前目录。

如果 dry_run 为 true,则不创建归档,但会将要执行的操作记录到 logger 中。

ownergroup 用于创建 tar 归档。默认情况下,使用当前所有者和组。

logger 必须是与 PEP 282 兼容的对象,通常是 logging.Logger 的实例。

verbose 参数未使用且已弃用。

引发带有参数 base_nameformatroot_dirbase_dir审计事件 shutil.make_archive

备注

当使用 register_archive_format() 注册的自定义归档器不支持 root_dir 参数时,此函数不是线程安全的。在这种情况下,它会暂时将进程的当前工作目录更改为 root_dir 以执行归档。

3.8 版本中已更改: 现在,对于使用 format="tar" 创建的归档文件,使用现代 pax (POSIX.1-2001) 格式,而不是传统的 GNU 格式。

3.10.6 版本中已更改: 此函数在创建标准 .zip 和 tar 归档时现在是线程安全的。

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 模块可用)。

  • zstdtar: Zstandard 压缩的 tar 文件(如果 compression.zstd 模块可用)。

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

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

注册格式 name 的归档器。

function 是用于解包归档的可调用对象。可调用对象将接收要创建的文件的 base_name,后跟开始归档的 base_dir(默认为 os.curdir)。进一步的参数将作为关键字参数传递:ownergroupdry_runlogger(与 make_archive() 中传递的相同)。

如果 function 具有自定义属性 function.supports_root_dir 且设置为 True,则 root_dir 参数将作为关键字参数传递。否则,在调用 function 之前,进程的当前工作目录将暂时更改为 root_dir。在这种情况下,make_archive() 不是线程安全的。

如果给定 extra_args,它是一个 (name, value) 对的序列,当使用归档器可调用对象时,它们将用作额外的关键字参数。

description 用于 get_archive_formats() 返回归档器列表。默认为空字符串。

3.12 版本中已更改: 添加了对支持 root_dir 参数的函数的支持。

shutil.unregister_archive_format(name)

从支持的格式列表中移除归档格式 name

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

解压一个归档。filename 是归档的完整路径。

extract_dir 是归档解压到的目标目录的名称。如果未提供,则使用当前工作目录。

format 是归档格式:可以是“zip”、“tar”、“gztar”、“bztar”、“xztar”或“zstdtar”。或任何其他使用 register_unpack_format() 注册的格式。如果未提供,unpack_archive() 将使用归档文件名扩展名,并查看是否有为此扩展名注册的解压器。如果未找到,则会引发 ValueError

仅关键字参数 filter 会传递给底层解压函数。对于 zip 文件,不接受 filter。对于 tar 文件,建议使用 'data'(Python 3.14 以来默认),除非使用 tar 和类 UNIX 文件系统特有的功能。(有关详细信息,请参阅 解压过滤器。)

引发带有参数 filenameextract_dirformat审计事件 shutil.unpack_archive

警告

切勿在未经事先检查的情况下从不受信任的来源提取归档。文件可能会在 extract_dir 参数中指定的路径之外创建,例如具有以“/”开头的绝对文件名或具有两个点“..”的文件名的成员。

自 Python 3.14 以来,所有内置格式(zip 和 tar 文件)的默认设置都将阻止此类最危险的安全问题,但不会阻止 所有 意外行为。阅读 进一步验证的提示 部分以了解 tar 特定的详细信息。

3.7 版本中已更改: filenameextract_dir 都接受 路径类对象

3.12 版本中已更改: 添加了 filter 参数。

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

注册解压格式。name 是格式的名称,extensions 是与格式对应的扩展名列表,例如 Zip 文件的 .zip

function 是用于解包归档的可调用对象。可调用对象将接收

  • 归档的路径,作为位置参数;

  • 归档必须解压到的目录,作为位置参数;

  • 可能有一个 filter 关键字参数,如果它已传递给 unpack_archive()

  • 附加的关键字参数,由 extra_args 指定为 (name, value) 元组的序列。

可以提供 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 模块可用)。

  • zstdtar: Zstandard 压缩的 tar 文件(如果 compression.zstd 模块可用)。

您可以使用 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/myarchive.tar'

列出生成的归档中的文件,我们得到

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

查询输出终端的大小

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

获取终端窗口的大小。

对于两个维度,分别会检查环境变量 COLUMNSLINES。如果变量已定义且值为正整数,则使用该值。

COLUMNSLINES 未定义时(这是常见情况),则通过调用 os.get_terminal_size() 查询连接到 sys.__stdout__ 的终端。

如果终端大小无法成功查询,原因可能是系统不支持查询,或者我们没有连接到终端,则使用 fallback 参数中给定的值。fallback 默认为 (80, 24),这是许多终端模拟器使用的默认大小。

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

另请参阅:Single UNIX Specification, Version 2, 其他环境变量

在 3.3 版本加入。

版本 3.11 中的变化: 如果 os.get_terminal_size() 返回零,也会使用 fallback 值。