下面的函数均默认from shutil import *
首先shutil中给出一个获取终端窗口尺寸的函数,感觉和其他的函数很不搭,所以单独写出来
>>> from shutil import *
>>> get_terminal_size()
os.terminal_size(columns=113, lines=39)
此外,还有一个看似很有用的小函数,disk_usage用于查看路径所在磁盘的使用情况,包括总量、已用和未用,形式为
>>> disk_usage("./test.md")
usage(total=622775496704, used=201395466240, free=421380030464)
shutil中有5个函数,输入参数均为src, dst, follow_symlinks,表示将src复制到dst,二者均为路径类对象或字符串形式的路径名;follow_symlinks默认为True,表示当src为链接时,操作这个链接对应的文件,否则将链接本身当作文件看待。
| 函数 | 复制内容 |
|---|---|
| copyfile | 文件内容 |
| copymode | 权限位 |
| copystat | 权限位、最近访问时间、最近修改时间以及旗标 |
| copy | 若dst为路径,则将src复制到dst中 |
| copy2 | 在copy的基础上,尝试保留文件的元数据 |
此外,还提供了操作文件对象的函数:copyfileobj(fsrc, fdst[, length]),其中length为正值时表示缓冲区大小,为负值表示拷贝数据时不对源数据进行分块循环处理。
如果只是赋值一个文件,那还体会不到shutil作为高阶文件操作模块的威力,shutil的真正价值,体现在可以递归操作文件夹上,主要涉及到的函数有copytree, rmtree, move等。
递归这个词之所以出现,与目录系统的组织形式是分不开的。尽管大家已经习惯了拖拽或者右键的方法来直接对整个文件夹进行复制粘贴。但操作系统真正的执行过程是,遍历当前文件夹,得到文件夹下的所有子文件夹和文件,对子文件夹再度遍历,换言之,这种遍历是递归的,直到所有子文件夹内部都是文件为止。通过这种方式得到一个目录树,然后在目标位置,新建目录树中的文件夹,并将文件复制到对应的路径下。
这样看来,copytree这个词就非常直观了,其输入参数如下
copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False, dirs_exist_ok=False)
其中,src, dst, symlinks这三个参数与copy相同,其他参数的含义如下
copy_function 为复制文件时调用的复制函数,默认为copy2dirs_exist_ok 指明是否要在目标目录已存在时引发异常。ignore_dangling_symlinks,设为True时,可以屏蔽由于链接不存在引发的异常。ignore为一个用于筛选的函数,表示忽略条件,其输入为 copytree()所访问的目录以及os.listdir()所返回的目录内容,其返回值将被忽略。rmtree顾名思义,用于删除目录树
rmtree(path, ignore_errors=False, onerror=None)
function, path, excinfo,其中function是引发异常的函数;path是传递给function的路径名;excinfo将是由sys.exc_info()所返回的异常信息,onerror所引发的异常将不会被捕获。move即递归地移动文件夹,定义为move(src, dst, copy_function=copy2) ,需要注意的是,如果dst为目录,则src会被移至该目录下;如果是文件,则可能会被覆盖.
shutil中提供了用于创建和读取压缩和归档文件的高层级工具,依赖于 zipfile和tarfile等模块。
这些函数分为两类,即压缩和解压缩,每一类又包括查询、注册、注销和执行四个函数,故共计8个函数
| 压缩 | 解压 | |
|---|---|---|
| 查询 | get_archive_formats | get_unpack_formats |
| 注册 | register_archive_format | register_unpack_format |
| 注销 | unregister_archive_format | unregister_unpack_format |
| 执行 | make_archive | unpack_archive |
所谓查询,就是查看当前系统支持的归档格式,压缩和解压缩返回的数据格式是不同的,unpack_archive多了一个后缀名。
>>> for tup in shutil.get_archive_formats():
... print(tup)
...
('bztar', "bzip2'ed tar-file")
('gztar', "gzip'ed tar-file")
('tar', 'uncompressed tar file')
('xztar', "xz'ed tar-file")
('zip', 'ZIP file')
>>> for tup in shutil.get_unpack_formats():
... print(tup)
...
('bztar', ['.tar.bz2', '.tbz2'], "bzip2'ed tar-file")
('gztar', ['.tar.gz', '.tgz'], "gzip'ed tar-file")
('tar', ['.tar'], 'uncompressed tar file')
('xztar', ['.tar.xz', '.txz'], "xz'ed tar-file")
('zip', ['.zip'], 'ZIP file')
如果当前所支持的归档格式无法满足需求,就需要注册新的归档文件,压缩和解压缩的注册函数分别为
register_archive_format(name, function[, extra_args[, description]])register_unpack_format(name, extensions, function[, extra_args[, description]])其中,name是格式名,extensions是扩展名列表,description是关于这种压缩格式的描述,在调用查询函数的时候会用到。
function是用于压缩或者解压缩的函数,至少有两个参数src和dst,分别代表源路径和目标路径;如果还有其他参数,则在extra_args中以(name, value)的形式给出。
若想注销某种格式,只需将这种格式的name输入注销函数即可。
接下来就是最重要的压缩和解压函数,其中解压函数比较简单,只包括三个参数,后两个还是可选的。
unpack_archive(filename[, extract_dir[, format]])
其中filename就是带解压文件;extract_dir为解压目录,默认当前工作目录;format 是归档格式,具体可参见get_unpack_formats。
压缩函数相对复杂一点
make_archive(base_name, format[, root_dir[, base_dir[, dry_run[, owner[, group[, logger]]]]]])
其中
base_name 为无后缀的文件名format 是归档格式,可参考get_archive_formatsroot_dir 为归档文件的根目录,归档中的所有路径都将是它的相对路径,默认当前目录。base_dir 压缩文件所在路径,必须相对于root_dir给出,默认当前目录。dry_run为真值,则不会创建归档文件,但将要被执行的操作会被记录到 logger。owner 和 group 在创建tar文件时启用,默认为当前用户和分组。需要注意,root_dir和base_dir需要以绝对路径的形式给出。
接下来写一个简单的案例
from shutil import *
# 这一步是要生成一些用来压缩的文件,和压缩无关
import os
os.mkdir("test")
for i in range(10):
with open(f"test/{i}.txt",'w') as f:
f.write(str(i))
make_archive('test','zip',r'E:\Documents\00\1218\test')
# 返回值为'E:\\Documents\\00\\1218\\test.zip'