You are here:  Home » Python » shutil-高级文件操作(10)Python文件和目录访问模块(必读进阶Python教程)(参考资料)

shutil模块对文件和文件集合提供了许多高级操作。特别是,提供了支持文件复制和删除的功能。有关单个文件的操作,另请参阅该 os模块。

警告

即使是更高级别的文件复制功能(shutil.copy(), shutil.copy2())也无法复制所有文件元数据。

在POSIX平台上,这意味着文件所有者和组以及ACL都会丢失。在Mac OS上,不使用资源分支和其他元数据。这意味着资源将丢失,文件类型和创建者代码将不正确。在Windows上,不会复制文件所有者,ACL和备用数据流。

目录和文件操作

shutil.copyfileobjFSRCfdst [长度
在类文件对象的内容复制金管会的文件对象fdst。如果给定,则整数长度是缓冲区大小。特别地,负 长度值意味着复制数据而不以块的形式循环源数据; 默认情况下,数据以块的形式读取,以避免不受控制的内存消耗。请注意,如果fsrc对象的当前文件位置不为0,则仅复制从当前文件位置到文件末尾的内容。
shutil.copyfilesrcdst*follow_symlinks = True 
将名为src的文件的内容(无元数据)复制到名为dst的文件中 并返回dst。 srcdst是以字符串形式给出的路径名。 dst必须是完整的目标文件名; 查看shutil.copy() 接受目标目录路径的副本。如果srcdst 指定相同的文件,SameFileError则引发。

目的地位置必须是可写的; 否则,OSError 将引发例外。如果dst已经存在,它将被替换。使用此功能无法复制特殊文件,如字符或块设备和管道。

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

在版本3.3中更改:IOError曾经被提升而不是OSError。添加了follow_symlinks参数。现在返回dst

在版本3.4中更改:提升SameFileError而不是Error。由于前者是后者的子类,因此这种改变是向后兼容的。

异常shutil.SameFileError
如果source和destination in copyfile() 是同一个文件,则会引发此异常。

版本3.4中的新功能。

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

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

shutil.copystatsrcdst*follow_symlinks = True 
复制权限位,上次访问时间,上次修改时间以及从srcdst的标志。在Linux上,copystat()还尽可能复制“扩展属性”。文件内容,所有者和组不受影响。 srcdst是以字符串形式给出的路径名。

如果follow_symlinks为false,并且srcdst都引用符号链接,copystat()则将对符号链接本身进行操作,而不是符号链接引用的文件 – 从src符号链接读取信息 ,并将信息写入 dst符号链接。

注意

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

  • 如果是 ,则可以修改符号链接的权限位。os.chmod in os.supports_follow_symlinksTruecopystat()
  • 如果是 ,则可以修改符号链接的上次访问和修改时间。os.utime inos.supports_follow_symlinksTruecopystat()
  • 如果是 ,可以修改符号链接的标志。(不适用于所有平台。)os.chflags inos.supports_follow_symlinksTruecopystat()os.chflags

在部分或全部此功能不可用的平台上,当要求修改符号链接时, copystat()将复制它可以执行的所有操作。 copystat()永远不会失败。

请参阅os.supports_follow_symlinks 更多信息。

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

shutil.copysrcdst*follow_symlinks = True 
将文件src复制到文件或目录dst。 srcdst 应该是字符串。如果dst指定目录,则使用src中的基本文件名将文件复制到dst中。返回新创建文件的路径。

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

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

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

shutil.copy2srcdst*follow_symlinks = True 
copy()除了copy2() 同样尝试保留文件元数据之外的相同内容。

follow_symlinks为false且src是符号链接时,copy2()尝试将所有元数据从src符号链接复制 到新创建的dst符号链接。但是,并非所有平台都提供此功能。在部分或全部此功能不可用的平台上,copy2()将保留所有可用的元数据; copy2()永远不会失败。

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

版本3.3中更改:添加了follow_symlinks参数,尝试复制扩展文件系统属性(目前仅限Linux)。现在返回新创建文件的路径。

shutil.ignore_patterns*模式
这个工厂函数创建一个可以作为一个可调用一个函数 copytree()忽略说法,忽略匹配通配符式样的一个文件和目录的方式提供。请参阅下面的示例。
shutil.copytreesrcdstsymlinks = Falseignore = Nonecopy_function = copy2ignore_dangling_symlinks = False 
递归复制以src为根的整个目录树,返回目标目录。目标目录(由dst命名)必须不存在; 它将被创建以及缺少父目录。复制目录的权限和时间,使用复制copystat()单个文件 shutil.copy2()

如果符号链接为真,则源树中的符号链接在新树中表示为符号链接,并且只要平台允许,将复制原始链接的元数据; 如果为false或省略,则链接文件的内容和元数据将复制到新树中。

符号链接为false时,如果符号链接指向的文件不存在,则Error在复制过程结束时在异常中引发的错误列表中将添加异常。如果要使此异常静音,可以将可选的ignore_dangling_symlinks标志设置为true。请注意,此选项对不支持的平台没有影响os.symlink()

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

如果发生异常,Error则会引发一系列原因。

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

在版本3.3中更改:符号链接为false 时复制元数据。现在返回dst

版本3.2中已更改:添加了copy_function参数以便能够提供自定义复制功能。当符号链接为false 时,将ignore_dangling_symlinks参数添加到silent dangling符号链接错误中。

shutil.rmtreepathignore_errors = Falseonerror = None 

删除整个目录树; path必须指向目录(但不是指向目录的符号链接)。如果ignore_errors为true,则将忽略由删除失败导致的错误; 如果为false或省略,则通过调用onerror指定的处理程序来处理此类错误,或者,如果省略,则会引发异常。

注意

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

如果提供了onerror,则它必须是可调用的,它接受三个参数:functionpathexcinfo

第一个参数function是引发异常的函数; 这取决于平台和实施。第二个参数 path是传递给function的路径名。第三个参数 excinfo将是返回的异常信息 sys.exc_info()。通过抛出的异常的onerror不会被抓住。

版本3.3中已更改:添加了符号链接攻击抵抗版本,如果平台支持基于fd的功能,则会自动使用该版本。

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

版本3.3中的新功能。

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

如果目标是现有目录,则src将在该目录中移动。如果目标已存在但不是目录,则可能会根据os.rename()语义覆盖目标。

如果目标位于当前文件系统上,则os.rename()使用该目标。否则,使用copy_functionsrc复制到dst,然后删除。在符号链接的情况下, 将在dst中创建指向src目标的新符号链接,并且将删除src

如果给出copy_function,它必须是一个可调用的,它接受两个参数 srcdst,如果 不能使用,它将用于将src复制到destos.rename()。如果源是一个目录, copytree()则调用它,传递它copy_function()。默认的copy_functioncopy2()。使用copy()作为 copy_function允许移动成功时,它不可能也复制元数据,在没有任何复制元数据的费用。

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

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

shutil.disk_usage路径
将有关给定路径的磁盘使用情况统计信息作为命名元组返回 ,其属性为totalusedfree,它们是total,used和free space的总量,以字节为单位。在Windows上,路径必须是目录; 在Unix上,它可以是文件或目录。

版本3.3中的新功能。

可用性:Unix,Windows。

shutil.chownpathuser = Nonegroup = None 
更改给定路径的所有者用户和/或

user可以是系统用户名或uid; 同样适用于群体。至少需要一个参数。

另请参见os.chown()基础功能。

可用性:Unix。

版本3.3中的新功能。

shutil.whichcmdmode = os.F_OK | os.X_OKpath = None 
返回可执行文件的路径,如果调用了给定的cmd,该文件将运行。如果没有调用cmd,则返回None

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

如果未指定路径os.environ()则使用结果,返回“PATH”值或后退os.defpath

在Windows上,无论您是使用默认路径还是提供自己的路径,当前目录始终都会添加到路径中,这是命令shell在查找可执行文件时使用的行为。此外,在路径中查找 cmd时,将检查环境变量。例如,如果您调用,将搜索 以确定它应在路径 目录中查找。例如,在Windows上:PATHEXTshutil.which("python")which()PATHEXTpython.exe

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

 

版本3.3中的新功能。

异常shutil.Error
此异常收集在多文件操作期间引发的异常。因为copytree(),exception参数是一个3元组的列表(srcnamedstnameexception)。

copytree示例

这个例子是copytree()上面描述的函数的实现,省略了docstring。它演示了该模块提供的许多其他功能。

def copytree(src, dst, symlinks=False):
    names = os.listdir(src)
    os.makedirs(dst)
    errors = []
    for name in names:
        srcname = os.path.join(src, name)
        dstname = os.path.join(dst, name)
        try:
            if symlinks and os.path.islink(srcname):
                linkto = os.readlink(srcname)
                os.symlink(linkto, dstname)
            elif os.path.isdir(srcname):
                copytree(srcname, dstname, symlinks)
            else:
                copy2(srcname, dstname)
            # XXX What about devices, sockets etc.?
        except OSError as why:
            errors.append((srcname, dstname, str(why)))
        # catch the Error from the recursive copytree so that we can
        # continue with other files
        except Error as err:
            errors.extend(err.args[0])
    try:
        copystat(src, dst)
    except OSError as why:
        # can't copy file access times on Windows
        if why.winerror is None:
            errors.extend((src, dst, str(why)))
    if errors:
        raise Error(errors)

 

使用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回调清除readonly位并重新尝试删除。任何后续故障都会传播。

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格式的支持。

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

shutil.make_archiveBASE_NAME格式[ROOT_DIR [base_dir [冗长[dry_run [所有者[[记录器
创建存档文件(例如zip或tar)并返回其名称。

base_name是要创建的文件的名称,包括路径,减去任何特定于格式的扩展名。format是存档格式:“zip”(如果zlib模块可用),“tar”,“gztar”(如果 zlib模块可用),“bztar”(如果bz2模块可用)或“xztar”(如果该lzma模块可用)。

root_dir是一个目录,它将成为存档的根目录; 例如,我们通常在创建存档之前将chdir转换为root_dir

base_dir是我们开始归档的目录; 即base_dir将是归档中所有文件和目录的公共前缀。

root_dirbase_dir都默认为当前目录。

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

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

记录器必须是与之兼容的对象PEP 282,通常是一个实例 logging.Logger

详细参数是未使用和废弃。

shutil.get_archive_formats
返回支持的归档格式列表。返回序列的每个元素都是元组。(name, description)

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

  • zip:ZIP文件(如果zlib模块可用)。
  • tar:未压缩的tar文件。
  • gztar:gzip’ed tar-file(如果zlib模块可用)。
  • bztar:bzip2’ed tar-file(如果该bz2模块可用)。
  • xztar:xz’ed tar-file(如果lzma模块可用)。

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

shutil.register_archive_format名称功能[extra_args [description 
注册格式名称的归档程序。

function是用于解压缩档案的可调用函数。callable将接收要创建的文件的base_name,然后是 base_dir(默认为os.curdir)以开始归档。进一步的参数作为关键字参数传递:ownergroup, dry_runlogger(传入make_archive())。

如果给定,extra_args是一对对的序列,当使用archiver callable时,它将用作额外的关键字参数。(name,value)

使用descriptionget_archive_formats()返回归档器列表。默认为空字符串。

shutil.unregister_archive_format名字
从支持的格式列表中删除存档格式名称
shutil.unpack_archivefilename [extract_dir [format 
解压缩档案。filename是存档的完整路径。

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

format是存档格式:“zip”,“tar”,“gztar”,“bztar”或“xztar”之一。或者注册的任何其他格式register_unpack_format()。如果未提供,unpack_archive() 将使用存档文件扩展名,并查看是否为该扩展注册了解包器。如果没有找到,ValueError则引发a。

改变在3.7版本:接受一个路径状物体文件名EXTRACT_DIR

shutil.register_unpack_format名称扩展功能[extra_args [description 
注册解包格式。name是格式的名称,而 扩展名是与格式相对应的扩展名列表,例如 .zipZip文件。

function是用于解压缩档案的可调用函数。callable将接收归档的路径,然后是必须提取归档的目录。

提供时,extra_args是一系列元组,它们将作为关键字参数传递给callable。(name, value)

描述可被提供来描述的格式,并且将被返还get_unpack_formats()的功能。

shutil.unregister_unpack_format名字
取消注册解压缩格式。name是格式的名称。
shutil.get_unpack_formats
返回所有已注册格式的列表以进行解包。返回序列的每个元素都是元组 。(name, extensions, description)

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

  • zip:ZIP文件(解压缩压缩文件仅在相应模块可用时才有效)。
  • tar:未压缩的tar文件。
  • gztar:gzip’ed tar-file(如果zlib模块可用)。
  • bztar:bzip2’ed tar-file(如果该bz2模块可用)。
  • xztar:xz’ed tar-file(如果lzma模块可用)。

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

存档示例

在这个例子中,我们创建了一个gzip’ed 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

 

查询输出终端的大小

shutil.get_terminal_sizefallback =(列行)
获取终端窗口的大小。

对于每个两个维度,该环境变量中,COLUMNS 并LINES分别被检查。如果定义了变量并且值是正整数,则使用它。

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

如果无法成功查询终端大小,或者因为系统不支持查询,或者因为我们未连接到终端,fallback则使用参数中给出的值。fallback默认值是许多终端仿真程序使用的默认大小。(80, 24)

返回的值是类型的命名元组os.terminal_size

另请参见:Single UNIX Specification,Version 2, Other Environment Variables

版本3.3中的新功能。