介绍

shutil模块包括一些高层文件操作,如赋值和归档

复制文件

import shutil

'''
copyfile将源文件的内容复制到目标文件,如果没有权限写目标文件,则会产生一个IOError
'''
# copyfile(源文件,目的文件)
shutil.copyfile(r"C:python37Libasyncioase_futures.py", "copy_base_futures.py")
'''
这个函数底层是使用copyfileobj,copyfileobj接收的是文件句柄。
因此copyfile这个函数会打开输入文件进行读取,所以某些特殊文件(如Unix的设备节点)不可以通过copyfile复制为新的特殊文件。
'''

# copy(源文件, 目的文件或者目录)
'''
对于copyfile来说,必须是文件。如果目的文件我们指定了一个目录(比如temp),得到的依旧是一个名为temp的文件
但是对于copy来说,如果目的文件我们指定了一个目录,那么会将文件拷贝到这个目录里面去,新的文件名和源文件名一致。但如果目录不存在那么和copyfile是一样的。
'''
shutil.copy(r"C:python37Libasyncioase_futures.py", r"666")
# 如果存在名为666的目录,那么会在666目录中创建一个名为base_futures.py的文件。如果不存在,那么会在当前目录创建一个名为666的文件
# 如果是copyfile的话,那么无论666这个目录存在与否,都是在当前目录创建一个名为666的文件


# copy2:和copy类似,只不过copy只是拷贝文件内容,copy2除了拷贝文件内容还会拷贝文件的访问和修改时间。
# 得到的文件和源文件的所有特性都相同

复制文件元数据

默认地,在Unix下创建一个新文件时,它会根据当前用户的unmask接收权限。
要把权限从一个文件复制到另外一个文件,可以使用copymode
要为文件复制其他元数据,可以使用copystat

处理目录树

import shutil

'''
shutil包含3个函数来处理目录树。
要把一个目录从一个位置复制到另外一个位置,可以使用copytree,这个函数会递归遍历目录树,将文件复制到目标位置。目标目录不能存在,存在的话会报错
'''
# 别看我目的目录指定的文件的格式,但是还是会创建一个目录,只不过这个目录就叫做aa.py
# 因此执行完之后会在我的当前目录中创建一个名为aa.py的目录,然后会把C:python37Libasyncio里面的内容全部拷贝到aa.py里面来
shutil.copytree(r"C:python37Libasyncio", r"aa.py")

# 如果要把一个文件或者目录移动到另外一个位置,可以使用move
# 类似于Unix下的mv命令,如果源和目标都在同一个文件夹中,那么属于重命名。如果不在,那么会先将源文件复制到目标文件,然后再删除源文件
# 这里不再演示

注意:无论拷贝还是move,都是指令的目录里面的内容,目录本身是不会拷贝或者移动的。 

查找文件

import shutil

'''
which函数会扫描一个路径以查找一个命名文件。
典型的用法是在环境变量PATH定义的shell搜索路径中查找一个可执行程序。
'''
print(shutil.which("go"))  # C:Goingo.EXE
print(shutil.which("python"))  # C:Python37python.EXE
print(shutil.which("aaa"))  # None

# 除此之外还可以指定路径,如果不指定路径,那么默认是os.environ("PATH")
# 但是查找文件可以使用之前说到的pathlib
import pathlib

p = pathlib.Path(r"C:python37Libsite-packagespandas")
for name in p.rglob("frame.py"):
    print(name)
r'''
C:python37Libsite-packagespandascoreframe.py
C:python37Libsite-packagespandascoresparseframe.py
'''

归档

import shutil

'''
Python的标准库包含很多模块来管理归档文件,如tarfile和zipfile。
另外shutil中也提供了很多更高层的函数来创建和解压归档文件。
get_archive_formats函数可以查看当前系统上支持的所有格式的名字和描述
'''
for name, format in shutil.get_archive_formats():
    print(name, ":", format)
'''
bztar : bzip2'ed tar-file
gztar : gzip'ed tar-file
tar : uncompressed tar file
xztar : xz'ed tar-file
zip : ZIP file
'''
# 支持的格式取决于有哪些模块和底层库。因此根据这个例子在哪里运行,它的输出可能会有所变化。


# 可以使用make_archive函数来创建一个新的归档文件,说白了就是压缩包。
# shutil.make_archive(压缩之后的文件名, 压缩的格式, 要压缩的文件或目录)
# 会自动将压缩之后的文件名和压缩的格式组合起来
shutil.make_archive(r"asyncio", "zip", r"C:python37Libasyncio")
# 表示将C:python37Libasyncio下面的所有文件打包成zip格式放到当前目录下,压缩后的文件叫做asyncio.zip
# 当然压缩之后的文件名还可以是一个路径,如果是"D:satoriasyncio"的话,那么得到的就是D:satoriasyncio.zip,总之就是将其和压缩的格式组合起来


# 除此之外,还可以对一个压缩包进行解包
# shutil.unpack_archive(压缩包的名字, 解压到的位置, 压缩格式)
# 另外压缩格式如果不传,那么会自动根据压缩包的扩展名来判断到底该采用哪种格式来解压缩

文件系统空间

import shutil

'''
完成一个长时间运行、可能耗尽可用空间的操作之前,最好先检查本地文件系统,来看看有多少可用的空间,这会很有用。
disk_usage函数会返回一个元组,包括总空间、当前正在使用的空间、以及未用的空间(自由空间)
'''
total_bytes, used_bytes, free_bytes = shutil.disk_usage("C:")
print(total_bytes / 1024 / 1024 / 1024)  # 222.78890991210938
print(used_bytes / 1024 / 1024 / 1024)  # 51.60057830810547
print(free_bytes / 1024 / 1024 / 1024)  # 171.1883316040039

# 除此之外可以使用psutil这个模块
import psutil

# 可以看到,帮我们把所用比例都算出来了,目前用了百分之23.2
print(psutil.disk_usage("C:"))  # sdiskusage(total=239217770496, used=55405699072, free=183812071424, percent=23.2)