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
以命名元组的方式(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)