shutil 标准库: Python 文件操作的万用刀

今天来聊一个被低估的 Python 标准库 - shutil 。工作中我们用 Python (尤其是写一些短小轻快的脚本)虽然经常和文件打交道,却很少用到 shutil 。但实际上, shutil 提供了比 os 模块更高级的文件操作接口,能让我们写出更 Pythonic 的代码。

从一个真实场景说起

最近在整理项目代码时,需要将散落在各处的配置文件归类到统一目录。按以往的习惯,我会这样写:

import os# 创建目标目录
if not os.path.exists("configs"):os.makedirs("configs")# 移动文件
for root, dirs, files in os.walk("."):for file in files:if file.endswith(".conf"):src = os.path.join(root, file)dst = os.path.join("configs", file)os.rename(src, dst)

这段代码能完成任务,但存在几个问题:

  1. 如果目标路径已存在同名文件会报错
  2. 不支持跨设备移动
  3. 没有保留文件的元数据(权限、时间戳等)

用 shutil 可以优雅地解决这些问题:

import shutil
import osos.makedirs("configs", exist_ok=True)
for root, dirs, files in os.walk("."):for file in files:if file.endswith(".conf"):src = os.path.join(root, file)dst = os.path.join("configs", file)shutil.move(src, dst)

看起来差别不大,但 shutil.move() 会:

  • 当目标路径已存在同名文件时, shutil.move() 的行为取决于操作系统
    • Windows: 如果目标文件存在且正在使用,会抛出 PermissionError ;否则会静默覆盖目标文件
    • Unix/Linux: 会遵循操作系统的规则。如果用户有权限,会覆盖目标文件;否则抛出 PermissionError
  • 支持跨设备移动
    • "跨设备"指的是在不同的文件系统或存储设备之间移动文件,比如从 C 盘移动到 D 盘、从本地磁盘移动到网络驱动器、从固态硬盘移动到 U 盘
    • shutil.move() 会首先尝试使用 os.rename() ,如果失败且错误是跨设备错误 errno.EXDEV ,则复制文件到目标位置,验证复制成功,最后删除源文件
  • 保留源文件的所有元数据

shutil 常用操作详解

1. 复制文件和目录

# 复制文件
shutil.copy("source.txt", "dest.txt")      # 复制文件内容
shutil.copy2("source.txt", "dest.txt")     # 复制文件内容和元数据# 复制目录
shutil.copytree("src_dir", "dst_dir")      # 递归复制整个目录树

copy2() 比 copy() 多了preserving metadata 的功能,在需要保留文件属性时很有用。

2. 删除目录

# 删除目录树
shutil.rmtree("dir_to_remove")             # 递归删除目录及其内容

os.rmdir() 强大,后者只能删除空目录。

3. 磁盘使用统计

total, used, free = shutil.disk_usage(".")
print(f"总空间: {total // (2**30)} GiB")
print(f"已使用: {used // (2**30)} GiB")
print(f"可用: {free // (2**30)} GiB")

直观地获取磁盘使用情况,免去了手动计算的麻烦。

4. 文件打包与压缩

# 创建压缩包
shutil.make_archive("backup", "zip", "source_dir")   # 支持zip、tar等格式# 解压缩
shutil.unpack_archive("backup.zip", "extract_dir")

实用脚本示例

1. 项目备份工具

import shutil
from datetime import datetime
import osdef backup_project(project_path, backup_dir="backups"):# 创建以时间戳命名的备份文件timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")backup_name = f"backup_{timestamp}"# 确保备份目录存在os.makedirs(backup_dir, exist_ok=True)# 创建压缩包archive_path = shutil.make_archive(os.path.join(backup_dir, backup_name),"zip",project_path)print(f"备份完成: {archive_path}")

2. 大文件搬运工具

import shutil
import os
from pathlib import Pathdef move_large_files(src_dir, dst_dir, min_size_mb=100):"""移动大于指定大小的文件到目标目录"""dst_path = Path(dst_dir)dst_path.mkdir(exist_ok=True)for root, _, files in os.walk(src_dir):for file in files:file_path = Path(root) / fileif file_path.stat().st_size > min_size_mb * 1024 * 1024:try:shutil.move(str(file_path), dst_path / file)print(f"已移动: {file}")except Exception as e:print(f"移动失败 {file}: {e}")

3. 智能文件分类器

import shutil
from pathlib import Path
import mimetypesdef organize_files(directory):"""根据文件类型自动分类文件"""directory = Path(directory)# 遍历所有文件for file_path in directory.rglob("*"):if file_path.is_file():# 获取文件类型mime_type, _ = mimetypes.guess_type(str(file_path))if mime_type:category = mime_type.split("/")[0]# 创建分类目录dest_dir = directory / categorydest_dir.mkdir(exist_ok=True)# 移动文件try:shutil.move(str(file_path), str(dest_dir / file_path.name))except Exception as e:print(f"处理{file_path}时出错: {e}")

性能提示

  1. 对于大文件操作,shutil 提供了 copyfileobj() 方法,支持设置缓冲区大小:
with open("source.dat", "rb") as fsrc:with open("dest.dat", "wb") as fdst:shutil.copyfileobj(fsrc, fdst, length=1024*1024)  # 1MB buffer
  1. copytree() 支持多进程并行复制:
from multiprocessing import Pooldef copy_with_progress(src, dst):shutil.copy2(src, dst)return dstwith Pool(processes=4) as pool:shutil.copytree("src_dir", "dst_dir", copy_function=pool.map)

文件属性操作

1. 权限和所有权

import shutil
import osdef mirror_permissions(src, dst):# 复制权限位shutil.copymode(src, dst)# 复制所有权(需要root权限)try:shutil.chown(dst, user=os.stat(src).st_uid,group=os.stat(src).st_gid)except PermissionError:print("需要管理员权限来修改所有权")

2. 元数据复制

import shutil
import os
from datetime import datetimedef show_metadata(path):stat = os.stat(path)print(f"访问时间: {datetime.fromtimestamp(stat.st_atime)}")print(f"修改时间: {datetime.fromtimestamp(stat.st_mtime)}")print(f"创建时间: {datetime.fromtimestamp(stat.st_ctime)}")print(f"权限: {oct(stat.st_mode)[-3:]}")print(f"大小: {stat.st_size} bytes")# 复制文件并保留所有元数据
src = "source.txt"
dst = "dest.txt"
shutil.copy2(src, dst)print("源文件元数据:")
show_metadata(src)
print("\n目标文件元数据:")
show_metadata(dst)

总结

shutil 是一个设计优雅的文件操作库:

  • 提供了比 os 模块更高级的接口
  • 自动处理各种边界情况
  • 保持了 Python “batteries included” 的理念

下次遇到文件操作需求,不妨先看看 shutil 是否已经提供了合适的工具。毕竟,"不要重复发明轮子"也是 Python 的哲学之一。

希望这篇文章对你有帮助!如果觉得有用,欢迎点赞转发~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/493620.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据机器学习算法和计算机视觉应用07:机器学习

Machine Learning Goal of Machine LearningLinear ClassificationSolutionNumerical output example: linear regressionStochastic Gradient DescentMatrix Acceleration Goal of Machine Learning 机器学习的目标 假设现在有一组数据 x i , y i {x_i,y_i} xi​,yi​&…

DB-GPT V0.6.3 版本更新:支持 SiliconCloud 模型、新增知识处理工作流等

DB-GPT V0.6.3版本现已上线,快速预览新特性: 新特性 1. 支持 SiliconCloud 模型,让用户体验多模型的管理能力 如何使用: 修改环境变量文件.env,配置SiliconCloud模型 # 使用 SiliconCloud 的代理模型 LLM_MODELsiliconflow_p…

ChromeOS 131 版本更新

ChromeOS 131 版本更新 1. ChromeOS Flex 自动注册 在 ChromeOS 131 中,ChromeOS Flex 的自动注册功能现已允许大规模部署 ChromeOS Flex 设备。与 ChromeOS 零接触注册类似,自动注册将通过组织管理员创建的注册令牌嵌入到 ChromeOS Flex 镜像中。这将…

你好Python

初识Python Python的起源 1989年,为了打发圣诞节假期,Gudio van Rossum吉多 范罗苏姆(龟叔)决心开发一个新的解释程序(Python雏形) 1991年,第一个Python解释器诞生 Python这个名字&#xff…

【Linux系统编程】:信号(2)——信号的产生

1.前言 我们会讲解五种信号产生的方式: 通过终端按键产生信号,比如键盘上的CtrlC。kill命令。本质上是调用kill()调用函数接口产生信号硬件异常产生信号软件条件产生信号 前两种在前一篇文章中做了介绍,本文介绍下面三种. 2. 调用函数产生信号 2.1 k…

BlueLM:以2.6万亿token铸就7B参数超大规模语言模型

一、介绍 BlueLM 是由 vivo AI 全球研究院自主研发的大规模预训练语言模型,本次发布包含 7B 基础 (base) 模型和 7B 对话 (chat) 模型,同时我们开源了支持 32K 的长文本基础 (base) 模型和对话 (chat) 模型。 更大量的优质数据 :高质量语料…

apache-tomcat-6.0.44.exe Win10

apache-tomcat-6.0.44.exe Win10

linux-----常用指令

文件和目录操作指令 ls(list)指令 功能:用于列出目录的内容,包括文件和子目录。示例: ls:列出当前目录下的所有非隐藏文件和目录。例如,在一个包含文件file1.txt、file2.txt和目录dir1的目录中&…

海外外卖APP开发新方向:基于同城外卖系统源码的多元化解决方案

时下,基于同城外卖系统源码的多元化解决方案,正成为海外外卖APP开发的新方向,推动着全球外卖市场的变革。本篇文章,小编将为大家讲述外卖APP开发的新方案。 一、同城外卖系统源码:创新与灵活的基础 同城外卖系统源码…

GhostRace: Exploiting and Mitigating Speculative Race Conditions-记录

文章目录 论文背景Spectre-PHT(Transient Execution )Concurrency BugsSRC/SCUAF和实验条件 流程Creating an Unbounded UAF WindowCrafting Speculative Race ConditionsExploiting Speculative Race Conditions poc修复flush and reload 论文 https:/…

「Mac畅玩鸿蒙与硬件46」UI互动应用篇23 - 自定义天气预报组件

本篇将带你实现一个自定义天气预报组件。用户可以通过选择不同城市来获取相应的天气信息,页面会显示当前城市的天气图标、温度及天气描述。这一功能适合用于动态展示天气信息的小型应用。 关键词 UI互动应用天气预报数据绑定动态展示状态管理 一、功能说明 自定义…

常用Python自动化测试框架有哪些?

随着技术的进步和自动化技术的出现,市面上出现了一些自动化测试框架。只需要进行一些适用性和效率参数的调整,这些自动化测试框架就能够开箱即用,大大节省了测试时间。而且由于这些框架被广泛使用,他们具有很好的健壮性&#xff0…

彻底认识和理解探索分布式网络编程中的SSL安全通信机制

探索分布式网络编程中的SSL安全通信机制 SSL的前提介绍SSL/TLS协议概述SSL和TLS建立在TCP/IP协议的基础上分析一个日常购物的安全问题 基于SSL的加密通信SSL的安全证书SSL的证书的实现安全认证获取对应的SSL证书方式权威机构获得证书创建自我签名证书 SSL握手通信机制公私钥传输…

嵌入式单片机的运行方式详解

程序的运行方式轮询系统 指的是在程序运行时,首先对所有的硬件进行初始化,然后在主程序中写一个死循环,需要运行的功能按照顺序进行执行,轮询系统是一种简单可靠的方式,一般适用于在只需要按照顺序执行的并且没有外部事件的影响的情况下。 程序的运行过程中出现如按键等需…

python如何保存.npy

数据处理的时候主要通过两个函数: (1)np.save(“test.npy”,数据结构) ----存数据 (2)data np.load(test.npy") ----取数据 给2个例子如下: 1、存列表 z [[[1, 2, 3], [w]…

gitee给DeployKey添加push权限

git执行push操作,将本地修改推送到gitee远程仓库时,报错: error: src refspec master does not match any error: failed to push some refs to gitee.com:XXX/XXX.git进一步执行以下强制推送命令: $ git push --set-upstream o…

Unbuntu下怎么生成SSL自签证书?

环境: WSL2 Unbuntu 22.04 问题描述: Unbuntu下怎么生成SSL自签证书? 解决方案: 生成自签名SSL证书可以使用OpenSSL工具,这是一个广泛使用的命令行工具,用于创建和管理SSL/TLS证书。以下是生成自签名…

Java模拟多个Mqtt客户端连接Mqtt Broker

上一次我们介绍了Java模拟单个Mqtt客户端的场景&#xff0c;但是在实际的业务场景中&#xff0c;可能需要我们模拟多个Mqtt客户端&#xff0c;比如&#xff1a;我们要对云平台的连接和设备上下行做压测。 Java模拟多个Mqtt客户端基本流程 引入Paho MQTT客户端库 <depende…

《Qt Creator 4.11.1 教程》

《Qt Creator 4.11.1 教程》 一、Qt Creator 4.11.1 概述&#xff08;一&#xff09;简介&#xff08;二&#xff09;界面构成 二、常用设置指南&#xff08;一&#xff09;环境设置&#xff08;二&#xff09;文本编辑器设置&#xff08;三&#xff09;构建和运行设置 三、构建…

LeetCode 热题 100_K 个一组翻转链表(31_25_困难_C++)(四指针法)

LeetCode 热题 100_K 个一组翻转链表&#xff08;31_25&#xff09; 题目描述&#xff1a;输入输出样例&#xff1a;题解&#xff1a;解题思路&#xff1a;思路一&#xff08;四指针法&#xff09;&#xff1a; 代码实现代码实现&#xff08;思路一&#xff08;四指针法&#x…