在日常的计算机使用中,文件与目录的复制、移动、删除、压缩是最常见不过的操作。比如:你需要定期把工作文件夹备份到移动硬盘;写一个脚本自动整理凌乱的桌面,将图片、文档分别归入不同目录;或者批量重命名并移动几百个照片文件。这些任务如果手动完成既繁琐又易错,而 Python 的shutil(Shell Utilities 的缩写)模块正是为此而生。它是对底层操作系统文件操作命令(如cp、mv、rm、tar)的高级封装,提供了跨平台的、更安全、更易用的接口。有了shutil,你只需一行shutil.copy(src, dst)就能实现文件复制,shutil.rmtree(path)可以递归删除整个目录树,甚至shutil.make_archive()能把文件夹打包成 zip 或 tar 文件。无论是编写数据备份脚本、构建自动化部署工具,还是日常清理下载文件夹,shutil都能让你用 Python 轻松驾驭文件系统。
安装
shutil是 Python 的标准库模块,因此不需要单独安装。只需确保 Python 环境(Python 3.x)已正确安装,即可通过import shutil直接使用。它依赖底层的操作系统 API,在 Windows、Linux、macOS 上均能无缝运行。
基本用法
下面分 4 个小步骤演示shutil的核心操作。
1. 复制文件
python
import shutil # 复制文件(保留权限信息,但不保留元数据如创建时间) shutil.copy('source.txt', 'destination.txt') # 复制文件并保留元数据(如修改时间) shutil.copy2('source.txt', 'dest_with_meta.txt') # 复制文件到目标目录(保持原文件名) shutil.copy('source.txt', './backup_folder/')2. 复制整个目录
python
# 递归复制整个目录树(目标目录必须不存在,否则报错) shutil.copytree('src_folder', 'dst_folder') # 复制时忽略某些文件或目录 shutil.copytree('src', 'dst', ignore=shutil.ignore_patterns('*.pyc', '__pycache__'))3. 移动文件或目录
python
# 移动文件/目录(类似于 mv 命令) shutil.move('old_location.txt', 'new_location.txt') # 也可以用来重命名(如果目标在同一父目录下) shutil.move('data.csv', 'backup.csv')4. 删除目录
python
# 删除一个非空目录及其所有内容(危险操作,谨慎使用) shutil.rmtree('temp_folder') # 更安全的删除:先检查是否存在 if shutil.os.path.exists('temp_folder'): shutil.rmtree('temp_folder')高级用法
shutil还提供了一些更强大的功能,适合复杂场景。
磁盘使用情况查询:获取文件系统剩余空间和总空间,便于在备份前检查磁盘容量。
python
total, used, free = shutil.disk_usage('/home') print(f"总空间: {total // (2**30)} GB, 剩余: {free // (2**30)} GB")创建归档文件:
make_archive可以将整个文件夹打包成 zip、tar、gztar 等格式,无需额外依赖。
python
# 将 'my_documents' 打包为 'backup.zip' 放在当前目录 archive_path = shutil.make_archive('backup', 'zip', 'my_documents') print(f"归档文件创建于: {archive_path}") # 支持格式:'zip', 'tar', 'gztar', 'bztar', 'xztar'解压归档文件:
unpack_archive能自动识别格式并解压。
python
shutil.unpack_archive('backup.zip', extract_dir='./restored')自定义复制回调函数:在复制大文件或目录时显示进度。
python
def progress_copied(src, dst, *args, **kwargs): print(f"正在处理: {src} -> {dst}") shutil.copytree('big_folder', 'big_folder_copy', copy_function=shutil.copy2, ignore_dangling_symlinks=True, dirs_exist_ok=True) # 注意:shutil.copytree 在 Python 3.8+ 支持 dirs_exist_ok 参数,允许覆盖已有目录文件权限与所有权:
shutil.copymode(src, dst)只复制权限,shutil.copystat(src, dst)复制权限和元数据。
实际应用场景
定期自动备份项目文件夹:假设你每天需要将
~/projects备份到外接硬盘的backups目录,并带日期后缀。
python
import shutil from datetime import datetime def backup_project(project_path, backup_root): project_name = shutil.os.path.basename(project_path) timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') backup_name = f"{project_name}_{timestamp}" backup_dest = shutil.os.path.join(backup_root, backup_name) shutil.copytree(project_path, backup_dest) print(f"备份完成: {backup_dest}") backup_project('/home/user/projects/awesome_app', '/media/external/backups')整理下载文件夹:自动将下载目录中的文件按扩展名移动到不同文件夹,并清理空目录。
python
from pathlib import Path import shutil downloads = Path.home() / 'Downloads' for item in downloads.iterdir(): if item.is_file(): ext = item.suffix[1:].lower() if item.suffix else 'no_ext' dest_dir = downloads / ext dest_dir.mkdir(exist_ok=True) shutil.move(str(item), str(dest_dir / item.name)) elif item.is_dir() and not any(item.iterdir()): item.rmdir() # 删除空目录
批量图片格式转换前的预处理:你需要将所有
.png文件复制到一个临时文件夹,进行转换后再移动回来。利用shutil.copy2保留原时间戳。
python
import shutil from pathlib import Path src_dir = Path('originals') tmp_dir = Path('tmp_convert') tmp_dir.mkdir(exist_ok=True) for png in src_dir.glob('*.png'): shutil.copy2(png, tmp_dir / png.name) # ... 在这里进行图像转换操作 ... # 转换完成后,移动回原目录并覆盖 for converted in tmp_dir.glob('*.png'): shutil.move(str(converted), str(src_dir / converted.name)) shutil.rmtree(tmp_dir)构建项目发布包:用
shutil.make_archive打包代码,同时忽略.git和测试文件夹。
python
import shutil import tempfile with tempfile.TemporaryDirectory() as tmpdir: # 将项目复制到临时目录,排除不必要的文件 shutil.copytree('my_project', f'{tmpdir}/my_project', ignore=shutil.ignore_patterns('.git', '__pycache__', '*.pyc', 'tests')) # 创建归档 shutil.make_archive('my_project_release', 'gztar', tmpdir, 'my_project') print("发布包生成完毕: my_project_release.tar.gz")结尾
shutil作为 Python 标准库中的文件操作专家,几乎覆盖了所有我们日常需要的文件系统操作。它既简洁又强大,无需调用外部命令就能完成跨平台的文件复制、移动、删除、打包等任务。从简单的数据备份到复杂的自动化部署流水线,shutil都能成为你脚本中的得力助手。相比于直接使用os.system('cp ...'),shutil提供了更好的异常处理和可读性,避免了 shell 注入风险。
最后,想问问你:在你的实际工作中,是否遇到过由于磁盘空间不足导致备份失败,或者需要实现“增量复制”(只复制新增或修改的文件)的场景?你知道如何结合shutil和filecmp模块来实现更智能的同步吗?欢迎在评论区分享你的经验和挑战,我们一起探讨更高效的文件管理方案!