shutil(shell utilities)是 Python 的标准库模块,提供了许多高级的文件和目录操作功能,比基本的 os 模块更强大和便捷。

主要功能分类

1. 文件和目录操作

复制操作

import shutil

# 复制文件
shutil.copy('source.txt', 'destination.txt')
shutil.copy2('source.txt', 'destination.txt')  # 保留元数据

# 复制目录
shutil.copytree('source_dir', 'destination_dir')

# 复制文件权限
shutil.copymode('source.txt', 'destination.txt')

# 复制文件状态信息(权限、时间等)
shutil.copystat('source.txt', 'destination.txt')

移动和重命名

# 移动文件或目录
shutil.move('source.txt', 'new_location/source.txt')
shutil.move('old_dir', 'new_dir')  # 重命名目录

删除目录

# 递归删除目录(包括所有内容)
shutil.rmtree('directory_to_delete')

2. 磁盘使用情况

# 获取磁盘使用统计
total, used, free = shutil.disk_usage('/path/to/directory')
print(f"总空间: {total // (1024**3)} GB")
print(f"已用空间: {used // (1024**3)} GB")
print(f"可用空间: {free // (1024**3)} GB")

3. 归档操作

# 创建归档文件
shutil.make_archive('backup', 'zip', 'directory_to_archive')
shutil.make_archive('backup', 'tar', 'directory_to_archive')
shutil.make_archive('backup', 'gztar', 'directory_to_archive')  # gzip压缩

# 解压归档文件
shutil.unpack_archive('backup.zip', 'extract_directory')
shutil.unpack_archive('backup.tar.gz', 'extract_directory')

4. 查找命令

# 查找可执行文件路径
python_path = shutil.which('python')
git_path = shutil.which('git')
print(f"Python路径: {python_path}")

常用方法详解

shutil.copy() vs shutil.copy2()

import shutil
import os

# 创建测试文件
with open('test.txt', 'w') as f:
    f.write('测试内容')

# copy() - 只复制内容
shutil.copy('test.txt', 'copy1.txt')

# copy2() - 复制内容和所有元数据
shutil.copy2('test.txt', 'copy2.txt')

# 比较文件状态
stat_orig = os.stat('test.txt')
stat_copy1 = os.stat('copy1.txt')
stat_copy2 = os.stat('copy2.txt')

print(f"原始文件修改时间: {stat_orig.st_mtime}")
print(f"copy1修改时间: {stat_copy1.st_mtime}")  # 可能不同
print(f"copy2修改时间: {stat_copy2.st_mtime}")  # 与原始相同

shutil.copytree() 高级用法

# 忽略特定文件类型
def ignore_patterns(*patterns):
    def ignore_func(path, names):
        ignored = []
        for pattern in patterns:
            ignored.extend(f for f in names if f.endswith(pattern))
        return set(ignored)
    return ignore_func

# 复制目录但忽略 .tmp 和 .log 文件
shutil.copytree('source_dir', 'dest_dir', 
                ignore=ignore_patterns('.tmp', '.log'))

# 或者使用预定义的忽略函数
shutil.copytree('source_dir', 'dest_dir', 
                ignore=shutil.ignore_patterns('*.tmp', '*.log'))

错误处理

import shutil
import os

def safe_remove(path):
    """安全删除目录"""
    try:
        if os.path.exists(path):
            shutil.rmtree(path)
            print(f"成功删除: {path}")
    except OSError as e:
        print(f"删除失败 {path}: {e}")

def safe_copy(src, dst):
    """安全复制文件"""
    try:
        shutil.copy2(src, dst)
        print(f"成功复制: {src} -> {dst}")
    except (OSError, IOError) as e:
        print(f"复制失败 {src} -> {dst}: {e}")

# 使用示例
safe_remove('temp_dir')
safe_copy('important.txt', 'backup/important.txt')

实际应用示例

1. 备份脚本

import shutil
import os
from datetime import datetime

def backup_directory(source_dir, backup_dir):
    """备份目录到带时间戳的压缩文件"""
    if not os.path.exists(source_dir):
        print(f"源目录不存在: {source_dir}")
        return
    
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    backup_name = f"backup_{os.path.basename(source_dir)}_{timestamp}"
    backup_path = os.path.join(backup_dir, backup_name)
    
    try:
        # 创建备份目录
        os.makedirs(backup_dir, exist_ok=True)
        
        # 创建压缩备份
        shutil.make_archive(backup_path, 'zip', source_dir)
        print(f"备份成功: {backup_path}.zip")
        
        # 检查磁盘空间
        total, used, free = shutil.disk_usage(backup_dir)
        free_gb = free // (1024**3)
        print(f"剩余磁盘空间: {free_gb} GB")
        
    except Exception as e:
        print(f"备份失败: {e}")

# 使用示例
backup_directory('/path/to/important_data', '/path/to/backups')

2. 文件同步工具

import shutil
import os
import filecmp

def sync_directories(source, destination):
    """同步两个目录"""
    # 如果目标目录不存在,直接复制
    if not os.path.exists(destination):
        shutil.copytree(source, destination)
        print(f"创建新目录: {destination}")
        return
    
    # 比较目录内容
    comparison = filecmp.dircmp(source, destination)
    
    # 复制新增和修改的文件
    for file in comparison.left_only + comparison.diff_files:
        src_file = os.path.join(source, file)
        dst_file = os.path.join(destination, file)
        
        if os.path.isdir(src_file):
            shutil.copytree(src_file, dst_file)
        else:
            shutil.copy2(src_file, dst_file)
        print(f"同步: {file}")
    
    # 删除目标目录中多余的文件
    for file in comparison.right_only:
        file_path = os.path.join(destination, file)
        if os.path.isdir(file_path):
            shutil.rmtree(file_path)
        else:
            os.remove(file_path)
        print(f"删除: {file}")

# 使用示例
sync_directories('source_dir', 'backup_dir')

3. 磁盘空间监控

import shutil
import time

def monitor_disk_space(path, threshold_gb=5):
    """监控磁盘空间,低于阈值时报警"""
    while True:
        total, used, free = shutil.disk_usage(path)
        free_gb = free // (1024**3)
        
        if free_gb < threshold_gb:
            print(f"警告: {path} 仅剩 {free_gb} GB 空间!")
            # 这里可以添加发送邮件或其他通知逻辑
        
        time.sleep(300)  # 每5分钟检查一次

# 使用示例
monitor_disk_space('/', 10)  # 监控根目录,阈值10GB

注意事项

  1. 权限问题: 确保有足够的权限执行文件操作
  2. 路径存在: 操作前检查路径是否存在
  3. 异常处理: 使用 try-except 处理可能的异常
  4. 大文件处理: 处理大文件时注意内存使用
  5. 跨平台兼容性: 某些功能在不同操作系统上可能表现不同

总结

shutil 模块提供了强大而便捷的文件和目录操作功能,是 Python 文件系统编程中不可或缺的工具。通过合理使用这些功能,可以轻松实现文件管理、备份、同步等常见任务。