bnmcvzx 2019-06-28
shutil模块提供了一些针对文件和目录的高级操作,主要是拷贝、移动。对于单个文件的操作,还可参考os模块
Warning:即使是高级别的拷贝函数(shutil.copy()
,shutil.copy2()
)也不能拷贝所有的文件元数据。意思是:在POSIX系统中,文件所有者、属组以及ACL信息会丢失。在Windows平台上,文件所有者,ACL以及ADS(供选数据流)不会被复制。On Mac OS, the resource fork and other metadata are not used. This means that resources will be lost and file type and creator codes will not be correct.
复制file-like
对象fsrc的内容到fdst,如果fdst不存在则自动创建。length表示缓冲大小,如果是负数表示直接复制,不循环遍历块中的源数据。数据默认按块读取(16 * 1024)避免不可控的内存消耗。
import shutil shutil.copyfileobj(open("fsrc.txt", "rb"), open("fdst.txt", "wb"))
复制文件src的内容到dst并返回dst,如果dst不存在则自动创建。src和dst是字符串类型的路径名,如果src和dst指向同一个文件,抛出SameFileError
异常。
目标位置必须是可写的,否则将抛出OSError
异常(实际抛出的是PermissionError
)。如果dst已经存在,则直接覆盖。特殊文件比如块设备、字符设备、管道不能使用此函数复制。
如果follow_symlinks为False且src是软链接,将创建一个新的软链接替代拷贝行为
shutil.copyfile("src.txt", "dst.txt")
复制文件src的权限位(permission bits)到dst,src和dst是字符串类型的路径名。如果follow_symlinks为False且src和dst都是软链接,将修改dst软链接文件而非源文件的权限。
此函数并非所有平台可用,如果它不能修改本地平台的软链接但又执行了相关操作,将不做任何操作直接返回None
# 修改前 -rw-r--r--. 1 root root 96 10月 11 12:26 aa.txt -rw-------. 1 root root 1362 9月 6 22:07 anaconda-ks.cfg -rw-------. 1 admin admin 0 10月 11 12:53 bb.txt lrwxrwxrwx. 1 root root 21 10月 11 12:58 cc.txt -> /root/anaconda-ks.cfg >>> shutil.copymode("aa.txt", "bb.txt") >>> shutil.copymode("aa.txt", "cc.txt") # 修改后 -rw-r--r--. 1 root root 96 10月 11 12:26 aa.txt -rw-r--r--. 1 root root 1362 9月 6 22:07 anaconda-ks.cfg -rw-r--r--. 1 admin admin 0 10月 11 12:53 bb.txt lrwxrwxrwx. 1 root root 21 10月 11 12:58 cc.txt -> /root/anaconda-ks.cfg
复制src的权限位、最后访问时间、最后修改时间以及标志(flag)到dst,src和dst是字符串类型的路径名,可以是文件或目录。在Linux平台上还会复制扩展属性。
如果follow_symlinks为False,且src和dst都是软链接,此函数直接操作软链接而非源文件(目录)。
Note:并非所有平台都能检查和修改软链接,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()可以修改软链接的flagcopystat()总是能成功执行,即使是在某些它的部分或全部功能不可用的平台上修改软链接,它将最大限度地拷贝它能拷贝的所有信息。
复制文件src的内容和权限位到dst,dst可以是文件或目录,如果是文件,函数的返回值就是dst,如果是目录,函数的返回值就是src的文件名与dst的路径拼接。src和dst都是字符串类型,如果dst指向一个目录,则创建与src同名(basename)的新文件。
如果follow_symlinks为False,且src是软链接,dst将作为软链接创建;如果follow_symlinks为True,src为软链接,则实际拷贝的是src指向的源文件。
copy()使用copymode()拷贝权限位,使用copyfile()拷贝文件内容
>>> shutil.copy("src.txt", "dst.txt") 'dst.txt' >>> shutil.copy("src.txt", "/tmp/") '/tmp/src.txt' >>> shutil.copy("src.txt", "/Dota2/") # 传入一个不存在的目录 Traceback (most recent call last): ... IsADirectoryError: [Errno 21] Is a directory: '/Dota2/'
除了还会保留src的所有元数据(如创建时间、修改时间等),其他与copy()相同。
当follow_symlinks为False且src为软链接时,dst将作为软链接被创建并拷贝src的所有元数据到dst。
copy2()使用copystat()拷贝元数据,使用copyfile()拷贝文件内容
创建并返回一个函数,可传递到copytree()中作为ignore参数的值,忽略满足匹配模式的文件和目录
递归复制以src为根目录的整个目录树,返回目标目录dst。dst必须是不存在的目录,它和它不存在的父目录都将被创建。使用copystat()
复制目录元数据,使用copy2()
复制文件内容和元数据
Error
异常中。os.symlink()
的平台,此参数无任何影响os.listdir()
返回的该目录下的文件、目录列表。由于copytree()是递归调用的,因此src目录树下每个被复制的目录都会调用一次ignore。原始目录结构:
[root@localhost Shutil]# pwd /root/Shutil [root@localhost Shutil]# ll -R .: 总用量 0 drwxr-xr-x. 3 root root 70 10月 12 10:48 src drwxr-xr-x. 3 root root 33 10月 12 10:47 symlink ./src: 总用量 0 -rw-r--r--. 1 root root 0 10月 12 10:39 aa.txt drwxr-xr-x. 2 root root 6 10月 12 10:40 dddir lrwxrwxrwx. 1 root root 27 10月 12 10:48 ssdir_link -> /root/Shutil/symlink/ssdir/ lrwxrwxrwx. 1 root root 27 10月 12 10:48 ss_link.txt -> /root/Shutil/symlink/ss.txt ./src/dddir: 总用量 0 ./symlink: 总用量 0 drwxr-xr-x. 2 root root 6 10月 12 10:57 ssdir -rw-r--r--. 1 root root 0 10月 12 10:46 ss.txt ./symlink/ssdir: 总用量 0
shutil.copytree("/root/Shutil/src/", "/root/Shutil/dst/", symlinks=False)
的执行结果:
[root@localhost Shutil]# ll dst/ 总用量 0 -rw-r--r--. 1 root root 0 10月 12 10:39 aa.txt drwxr-xr-x. 2 root root 6 10月 12 10:40 dddir drwxr-xr-x. 2 root root 6 10月 12 10:57 ssdir_link -rw-r--r--. 1 root root 0 10月 12 10:46 ss_link.txt
shutil.copytree("/root/Shutil/src/", "/root/Shutil/dst/", symlinks=True)
的执行结果:
[root@localhost Shutil]# ll dst/ 总用量 0 -rw-r--r--. 1 root root 0 10月 12 10:39 aa.txt drwxr-xr-x. 2 root root 6 10月 12 10:40 dddir lrwxrwxrwx. 1 root root 27 10月 12 10:48 ssdir_link -> /root/Shutil/symlink/ssdir/ lrwxrwxrwx. 1 root root 27 10月 12 10:48 ss_link.txt -> /root/Shutil/symlink/ss.txt
删除目录。path必须指代一个目录(但不能是目录的软链接)。
Note:在支持基于文件描述符的目录访问函数的平台上,默认使用抗软链接攻击(symlink attack resistant)的rmtree()版本;其他平台上的rmtree()的实现易遭受软链接攻击。可以用rmtree.avoids_symlink_attacks
查看当前平台的rmtree()方法能否抵抗软链接攻击
移动文件或目录到目标位置。
# before [root@localhost shutil_move]# pwd /root/shutil_move [root@localhost shutil_move]# ll 总用量 0 drwxr-xr-x. 2 root root 6 10月 12 14:41 dst_dir drwxr-xr-x. 2 root root 20 10月 12 14:39 src >>> shutil.move("/root/shutil_move/src/", "/root/shutil_move/dst_dir/") '/root/shutil_move/dst_dir/src' # after [root@localhost shutil_move]# ll -R .: 总用量 0 drwxr-xr-x. 3 root root 17 10月 12 14:43 dst_dir ./dst_dir: 总用量 0 drwxr-xr-x. 2 root root 6 10月 12 14:45 src ./dst_dir/src: 总用量 0
# before [root@localhost shutil_move]# pwd /root/shutil_move [root@localhost shutil_move]# ll 总用量 0 drwxr-xr-x. 2 root root 6 10月 12 14:55 src [root@localhost shutil_move]# ll /tmp/ 总用量 0 >>> shutil.move("/root/shutil_move/src/", "/tmp/a/b/dst/") '/tmp/a/b/dst/' # after [root@localhost shutil_move]# ll 总用量 0 [root@localhost shutil_move]# ll -R /tmp/ /tmp/: 总用量 0 drwxr-xr-x. 3 root root 15 10月 12 14:57 a /tmp/a: 总用量 0 drwxr-xr-x. 3 root root 17 10月 12 14:57 b /tmp/a/b: 总用量 0 drwxr-xr-x. 2 root root 6 10月 12 14:55 dst /tmp/a/b/dst: 总用量 0
如果dst非目录,且dst存在或其上级目录存在
以命名元组的方式(total, used, free)返回指定path的磁盘使用数据,单位为byte。在Windows平台,path必须指代目录;在Unix平台path可以是目录或文件
改变指定path的所有者和属组。
user和group参数,可以是系统上的用户名/组名或uid/gid。至少需要传递其中一个参数
返回cmd调用的可执行文件路径,没有返回None。
os.access()
的权限掩码(permission mask),默认值为os.F_OK | os.X_OK,用于判断文件是否存在或可执行。os.environ
的"PATH"key指代的路径查找,如果"PATH"不存在,使用os.defpath
作为默认路径。在Windows平台,不管使用默认path还是自定义的path,查找路径都将包含当前工作目录且处于最高优先级。此外,在查找cmd时,还会检查环境变量PATHEXT
。
>>> shutil.which("python3") 'D:\\Program Files\\Python36\\python3.EXE'
使用ignore_patterns()忽略拷贝后缀为.pyc的文件和tmp打头的文件或文件夹:
from shutil import copytree, ignore_patterns copytree(source, destination, ignore=ignore_patterns('*.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)
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)
基于zipfile和tarfile模块提供创建和读取归档文件的功能。
创建归档文件,并返回归档文件的名称。
# /root/demo/ 归档该目录下的文件和文件夹 # /tmp/shutil/ 生成的归档文件中的所有内容的前缀路径 >>> shutil.make_archive("/root/demo_zip/zipfile", "zip", "/root/demo/", "/tmp/shutil/") '/root/demo_zip/zipfile.zip'
[root@localhost demo_zip]# unzip -l zipfile.zip Archive: zipfile.zip Length Date Time Name --------- ---------- ----- ---- 0 10-15-2018 11:03 tmp/shutil/ 0 10-15-2018 11:03 tmp/shutil/aa.txt 0 10-15-2018 11:03 tmp/shutil/bb.txt 0 10-15-2018 11:03 tmp/shutil/cc.txt --------- ------- 0 4 files
返回支持的归档格式列表,列表中的每个元素是(name, description)形式的元组。
默认支持的格式如下:
用户可以通过register_archive_format()
注册新的格式或者自定义已存在格式的归档行为
注册格式为name的归档器
从支持的归档格式中移除name
解压归档文件。
ValueError
异常注册格式为name的解压器
从支持的解压格式中移除name
返回支持的解压格式列表,列表中的每个元素是(name, extensions, description)形式的元组。
获取终端窗口的大小。
如果环境变量中定义了正整数的COLUMNS
和LINES
,返回该大小。
如果COLUMNS
和LINES
未定义(多数情况都是如此),返回调用os.get_terminal_size()
查询连接到sys.__stdout__的终端的大小。
如果终端大小不能被查询(系统不支持或者未连接到终端),使用fallback参数提供的大小作为后备值,默认是(80, 24)