# 本文大纲

os 模块是 Python 标准库中一个重要的模块,里面提供了对目录和文件的一般常用操作。而 Python 另外一个标准库 ——shutil 库,它作为 os 模块的补充,提供了复制、移动、删除、压缩、解压等操作,这些 os 模块中一般是没有提供的。但是需要注意的是:shutil 模块对压缩包的处理是调用 ZipFile 和 TarFile 这两个模块来进行的。
图 1

# 知识串讲

本文所使用的素材,都是基于以下 2 个文件夹,其中一个文件夹为空。
图 2

# 1)模块导入

import shutil

# 2)复制文件

  • 函数:shutil.copy (src,dst)
  • 含义:复制文件;
  • 参数:src 表示源文件,dst 表示目标文件夹;
  • 注意:当移动到一个不存在的 “目标文件夹”,系统会将这个不存在的 “目标文件夹” 识别为新的文件夹,而不会报错;
# 1. 将 a 表的 “data.txt” 移动到 b 表
src = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_a\data.txt"
dst = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_b"
shutil.copy(src,dst)
------------------------------------------------------------
# 2. 将 a 表的 “data.txt” 移动到 b 表,并重新命名为 “new_data.txt”
src = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_a\data.txt"
dst = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_b\new_data.txt"
shutil.copy(src,dst)
------------------------------------------------------------
# 3. 将 a 表的 “data.txt” 移动到 “不存在” 的文件夹
src = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_a\data.txt"
dst = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_c"
shutil.copy(src,dst)
"""
注意:对于情况3,系统会默认将“test_shutil_c”识别为文件名,而不是按照我们认为的,移动到一个新的不存在的文件夹。
"""

结果如下:
图 3

# 3)复制文件夹

  • 函数:shutil.copytree (src,dst)
  • 含义:复制文件夹;
  • 参数:src 表示源文件夹,dst 表示目标文件夹;
  • 注意:这里只能是移动到一个空文件夹,而不能是包含其他文件的非空文件夹,否则会报错 PermissionError;

① 如果目标文件夹中存在其他文件,会报错;

# 将 a 文件夹移动到 b 文件夹,由于前面的操作,此时 b 文件夹中已经有其他文件
src = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_a"
dst = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_b"
shutil.copytree(src,dst)

结果如下:
图 4

② 如果指定任意一个目标文件夹,则会自动创建;

# c 文件夹原本是不存在的,我们使用了下方的代码,会自动创建该文件夹
src = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_a"
dst = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_c"
shutil.copytree(src,dst)

结果如下:
图 5

# 4)移动文件或文件夹

  • 函数:shutil.move (src,dst)
  • 含义:移动文件 / 文件夹; – 参数:src 表示源文件 / 文件夹,dst 表示目标文件夹;
  • 注意:文件 / 文件夹一旦被移动了,原来位置的文件 / 文件夹就没了。目标文件夹不存在时,会报错;
# 将当前工作目录下的 “a.xlsx” 文件,移动到 a 文件夹下
dst = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_a"
shutil.move("a.xlsx",dst)
----------------------------------------------------------------
# 将 a 文件夹下的 “a.xlsx” 文件,移动到 b 文件夹中,并重新命名为 “aa.xlsx”
src = r"C:/Users/黄伟/Desktop/publish/os模块/test_shutil_a\a.xlsx"
dst = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_b\aa.xlsx"
shutil.move(src,dst)

结果如下:
图 6
注意:移动文件夹操作类似,我这里就不赘述了,自行下去学习。

# 5)删除文件夹 (慎用)

  • 函数:shutil.rmtree (src)
  • 含义:删除文件夹;
  • 参数:src 表示源文件夹;
  • 注意:区别这里和 os 模块中 remove ()、rmdir () 的用法,remove () 方法只能删除某个文件,mdir () 只能删除某个空文件夹。但是 shutil 模块中的 rmtree () 可以递归彻底删除非空文件夹;
# 将 c 文件夹彻底删除
src = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_c"
shutil.rmtree(src)

结果如下:
图 7

# 6)创建和解压压缩包

  • zipobj.write ():创建一个压缩包;
  • zipobj.namelist ():读取压缩包中的文件信息;
  • zipobj.extract ():将压缩包中的单个文件,解压出来;
  • zipobj.extractall ():将压缩包中所有文件,解压出来;
  • shutil 模块对压缩包的处理是调用 ZipFile 和 TarFile 这两个模块来进行的,因此需要导入这两个模块;
  • 注意:这里所说的压缩包,指的是 “.zip” 格式的压缩包;

① 创建一个压缩包

import zipfile
import os
file_list = os.listdir(os.getcwd())
# 将上述所有文件,进行打包,使用 “w”
with zipfile.ZipFile(r"我创建的压缩包.zip", "w") as zipobj:
    for file in file_list:
        zipobj.write(file)

结果如下:
图 8

② 读取压缩包中的文件信息

import zipfile
with zipfile.ZipFile("我创建的压缩包.zip", "r") as zipobj:
    print(zipobj.namelist())

结果如下:
图 9

③ 将压缩包中的单个文件,解压出来

  • 注意:目标文件夹不存在,会自动创建;
import zipfile
# 将压缩包中的 “test.ipynb” 文件,单独解压到 a 文件夹下
dst = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_a"
with zipfile.ZipFile("我创建的压缩包.zip", "r") as zipobj:
    zipobj.extract("test.ipynb",dst)

结果如下:
图 10

④ 将压缩包中所有文件,解压出来;

  • 注意:目标文件夹不存在,会自动创建;
import zipfile
# 将压缩包中的所有文件,解压到 d 文件夹下
dst = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_d"
with zipfile.ZipFile("我创建的压缩包.zip", "r") as zipobj:
    zipobj.extractall(dst)

结果如下:
图 11