408 lines
11 KiB
Python
408 lines
11 KiB
Python
# Python 提供了强大的文件路径操作功能,主要使用 os.path 模块和 pathlib 模块。掌握路径操作对于文件管理、数据处理和跨平台开发至关重要。
|
|
# 核心概念
|
|
# 路径:指向文件或目录的字符串或对象
|
|
# 绝对路径:从根目录开始的完整路径
|
|
# 相对路径:相对于当前工作目录的路径
|
|
# 跨平台:不同操作系统使用不同的路径分隔符
|
|
|
|
# 导入必要模块
|
|
import os # 操作系统接口
|
|
import os.path # 传统路径操作
|
|
from pathlib import Path # 现代路径操作(推荐)
|
|
import glob # 文件通配符搜索
|
|
import shutil # 高级文件操作
|
|
|
|
# os.path 模块 - 传统路径操作
|
|
# 路径拼接和分解
|
|
# 路径拼接
|
|
# 使用 os.path.join() 自动处理不同操作系统的路径分隔符:
|
|
import os
|
|
|
|
# 路径拼接 - 自动处理分隔符
|
|
full_path = os.path.join("父文件夹", "子文件夹", "文件.txt")
|
|
print(full_path) # Linux/Mac: 父文件夹/子文件夹/文件.txt
|
|
# Windows: 父文件夹\子文件夹\文件.txt
|
|
|
|
# 获取文件名和目录名
|
|
import os
|
|
|
|
path = "/home/user/documents/file.txt"
|
|
|
|
# 获取文件名
|
|
print(os.path.basename(path)) # file.txt
|
|
|
|
# 获取目录名
|
|
print(os.path.dirname(path)) # /home/user/documents
|
|
|
|
# 分割路径
|
|
print(os.path.split(path)) # ('/home/user/documents', 'file.txt')
|
|
|
|
# 分离扩展名
|
|
import os
|
|
|
|
# 分离文件名和扩展名
|
|
name, ext = os.path.splitext("example.tar.gz")
|
|
print(name) # example.tar
|
|
print(ext) # .gz
|
|
|
|
# 获取绝对路径
|
|
import os
|
|
|
|
# 获取绝对路径
|
|
print(os.path.abspath("file.txt")) # 不解析符号链接
|
|
print(os.path.realpath("file.txt")) # 解析符号链接
|
|
|
|
# 路径检查和属性
|
|
# 函数 描述 返回值
|
|
# os.path.exists() 检查路径是否存在 True/False
|
|
# os.path.isfile() 检查是否为文件 True/False
|
|
# os.path.isdir() 检查是否为目录 True/False
|
|
# os.path.islink() 检查是否为符号链接 True/False
|
|
# os.path.getsize() 获取文件大小 字节数
|
|
# os.path.getmtime() 获取最后修改时间 时间戳
|
|
# os.path.getatime() 获取最后访问时间 时间戳
|
|
|
|
import os
|
|
|
|
path = "/home/user/documents"
|
|
|
|
# 检查路径属性
|
|
print(os.path.exists(path)) # True/False
|
|
print(os.path.isfile(path)) # True/False
|
|
print(os.path.isdir(path)) # True/False
|
|
print(os.path.islink(path)) # True/False
|
|
|
|
# 获取文件信息
|
|
if os.path.isfile(path):
|
|
print(f"文件大小: {os.path.getsize(path)} 字节")
|
|
print(f"修改时间: {os.path.getmtime(path)}")
|
|
|
|
|
|
# pathlib 模块 - 现代路径操作(推荐)
|
|
# pathlib 是 Python 3.4+ 引入的现代路径操作模块,提供面向对象的接口,更加直观和易用。
|
|
|
|
# 创建路径对象
|
|
from pathlib import Path
|
|
|
|
# 创建路径对象
|
|
path1 = Path("/home/user/documents") # 绝对路径
|
|
path2 = Path("relative/path") # 相对路径
|
|
path3 = Path.cwd() # 当前工作目录
|
|
path4 = Path.home() # 用户主目录
|
|
|
|
print(f"绝对路径: {path1}")
|
|
print(f"当前目录: {path3}")
|
|
print(f"用户主目录: {path4}")
|
|
|
|
# 路径对象优势
|
|
# 面向对象:更直观的 API 设计
|
|
# 跨平台:自动处理路径分隔符
|
|
# 链式操作:支持方法链式调用
|
|
# 类型安全:更好的类型提示支持
|
|
|
|
# 路径属性和方法
|
|
# 基本属性
|
|
from pathlib import Path
|
|
|
|
p = Path("/home/user/example/file.txt")
|
|
|
|
# 路径组成部分
|
|
print(f"完整路径: {p}") # /home/user/example/file.txt
|
|
print(f"文件名: {p.name}") # file.txt
|
|
print(f"文件名(无后缀): {p.stem}") # file
|
|
print(f"扩展名: {p.suffix}") # .txt
|
|
print(f"父路径: {p.parent}") # /home/user/example
|
|
print(f"磁盘/锚: {p.anchor}") # Linux: /, Windows: C:\
|
|
|
|
# 路径修改
|
|
# 路径修改方法
|
|
print(f"替换文件名: {p.with_name('data.csv')}") # /home/user/example/data.csv
|
|
print(f"替换扩展名: {p.with_suffix('.md')}") # /home/user/example/file.md
|
|
|
|
# 路径检查
|
|
# 基本检查
|
|
print(f"是否存在: {p.exists()}")
|
|
print(f"是否为文件: {p.is_file()}")
|
|
print(f"是否为目录: {p.is_dir()}")
|
|
print(f"是否为绝对路径: {p.is_absolute()}")
|
|
print(f"绝对路径: {p.resolve()}")
|
|
|
|
# 安全获取文件信息
|
|
# 安全地获取文件信息
|
|
if p.is_file():
|
|
stat = p.stat()
|
|
print(f"文件大小: {stat.st_size} 字节")
|
|
print(f"最后修改: {stat.st_mtime}")
|
|
else:
|
|
print("不是文件,无法获取大小和时间")
|
|
|
|
|
|
# 路径遍历和文件操作
|
|
# 目录遍历
|
|
from pathlib import Path
|
|
|
|
folder = Path("src")
|
|
|
|
# 遍历目录内容(非递归)
|
|
for item in folder.iterdir():
|
|
print(item)
|
|
|
|
# 使用通配符查找文件
|
|
for py_file in folder.glob("*.py"):
|
|
print(py_file)
|
|
|
|
# 递归查找文件
|
|
for py_file in folder.rglob("*.py"):
|
|
print(py_file)
|
|
|
|
# 目录创建
|
|
# 创建单个目录
|
|
new_folder = Path("new_directory")
|
|
new_folder.mkdir(exist_ok=True) # 已存在不报错
|
|
|
|
# 创建多级目录
|
|
deep_folder = Path("level1/level2/level3")
|
|
deep_folder.mkdir(parents=True, exist_ok=True)
|
|
|
|
# 常用遍历方法
|
|
# 方法 描述 递归
|
|
# iterdir() 列出目录内容 否
|
|
# glob(pattern) 通配符查找 否
|
|
# rglob(pattern) 递归查找 是
|
|
|
|
|
|
# 通配符模式
|
|
# *:匹配任意多个字符
|
|
# ?:匹配单个字符
|
|
# **:递归匹配(仅在 rglob 中有效)
|
|
|
|
# 常用路径操作示例
|
|
# 获取当前目录信息
|
|
import os
|
|
from pathlib import Path
|
|
|
|
# 获取当前工作目录
|
|
current_dir = os.getcwd() # 返回字符串
|
|
print(f"当前工作目录: {current_dir}")
|
|
|
|
# 使用 pathlib 获取当前目录
|
|
current_path = Path.cwd() # 返回 Path 对象
|
|
print(f"当前路径: {current_path}")
|
|
|
|
# 获取用户主目录
|
|
home_dir = Path.home()
|
|
print(f"用户主目录: {home_dir}")
|
|
|
|
|
|
# 路径规范化
|
|
from pathlib import Path
|
|
|
|
# 处理相对路径和符号链接
|
|
path = Path("../../Documents/../file.txt")
|
|
print(f"原始路径: {path}")
|
|
print(f"解析后路径: {path.resolve()}")
|
|
|
|
# 计算相对路径
|
|
base_path = Path("/home/user/documents")
|
|
target_path = Path("/home/user/documents/work/project/file.txt")
|
|
relative_path = target_path.relative_to(base_path)
|
|
print(f"相对路径: {relative_path}") # work/project/file.txt
|
|
|
|
# 文件路径操作综合示例
|
|
from pathlib import Path
|
|
|
|
# 定义多种路径示例
|
|
paths = [
|
|
"/home/user/documents/report.pdf",
|
|
"relative/path/file.txt",
|
|
"../parent/file.py",
|
|
"file_no_extension",
|
|
"archive.tar.gz",
|
|
]
|
|
|
|
# 分析每个路径
|
|
for path_str in paths:
|
|
path = Path(path_str)
|
|
print(f"\n分析路径: {path}")
|
|
print(f"文件名: {path.name}")
|
|
print(f"主干名: {path.stem}")
|
|
print(f"扩展名: {path.suffix}")
|
|
print(f"父目录: {path.parent}")
|
|
print(f"是否为绝对路径: {path.is_absolute()}")
|
|
|
|
|
|
# 文件和目录操作
|
|
# 文件操作
|
|
# 使用 pathlib 进行文件操作更加简洁和安全
|
|
from pathlib import Path
|
|
|
|
# 创建文件并写入内容
|
|
file_path = Path("test.txt")
|
|
file_path.write_text("Hello, World!", encoding="utf-8")
|
|
|
|
# 读取文件内容
|
|
content = file_path.read_text(encoding="utf-8")
|
|
print(content)
|
|
|
|
# 获取文件信息
|
|
if file_path.exists():
|
|
stat = file_path.stat()
|
|
print(f"文件大小: {stat.st_size} 字节")
|
|
print(f"最后修改: {stat.st_mtime}")
|
|
|
|
# 重命名文件
|
|
new_path = file_path.rename("new_test.txt")
|
|
|
|
# 文件操作优势
|
|
# 简洁性:一行代码完成文件读写
|
|
# 安全性:自动处理编码和异常
|
|
# 跨平台:自动处理路径分隔符
|
|
# 类型安全:更好的错误提示
|
|
|
|
# 目录操作
|
|
# 创建目录
|
|
from pathlib import Path
|
|
import shutil
|
|
|
|
# 创建单个目录
|
|
Path("example_dir").mkdir(exist_ok=True)
|
|
|
|
# 创建多级目录
|
|
Path("parent/child/grandchild").mkdir(parents=True, exist_ok=True)
|
|
|
|
# 遍历目录
|
|
# 遍历目录内容
|
|
folder = Path("example_dir")
|
|
print("目录内容:")
|
|
for item in folder.iterdir():
|
|
if item.is_dir():
|
|
print(f"目录: {item.name}")
|
|
else:
|
|
print(f"文件: {item.name}")
|
|
|
|
# 目录复制和删除
|
|
# 复制整个目录
|
|
shutil.copytree("example_dir", "copy_dir", dirs_exist_ok=True)
|
|
|
|
# 删除空目录
|
|
Path("empty_dir").mkdir(exist_ok=True)
|
|
Path("empty_dir").rmdir()
|
|
|
|
# 删除非空目录
|
|
shutil.rmtree("copy_dir")
|
|
|
|
# 目录操作优势
|
|
# 安全性:exist_ok=True 避免重复创建错误
|
|
# 递归性:parents=True 自动创建父目录
|
|
# 完整性:shutil 提供完整的目录操作
|
|
# 跨平台:自动处理不同操作系统的差异
|
|
|
|
# 跨平台路径处理
|
|
|
|
# 操作系统检测
|
|
from pathlib import Path
|
|
import os
|
|
|
|
# 根据操作系统选择路径
|
|
if os.name == "nt": # Windows
|
|
path = Path("C:/Users/Name/Documents")
|
|
else: # Unix/Linux/Mac
|
|
path = Path("/home/name/documents")
|
|
|
|
# 路径拼接
|
|
file_path = path / "subfolder" / "file.txt"
|
|
print(f"文件路径: {file_path}")
|
|
|
|
# 转换为字符串
|
|
path_str = str(file_path)
|
|
print(f"字符串路径: {path_str}")
|
|
|
|
# 跨平台优势
|
|
# 自动分隔符:pathlib 自动处理 / 和 \
|
|
# 路径标准化:统一路径表示方式
|
|
# 兼容性:代码在不同系统上都能正常工作
|
|
# 类型安全:Path 对象提供更好的类型提示
|
|
|
|
# 实用函数示例
|
|
# 文件查找函数
|
|
from pathlib import Path
|
|
|
|
|
|
def find_files_by_extension(directory, extension):
|
|
"""查找指定目录下指定扩展名的所有文件"""
|
|
directory_path = Path(directory)
|
|
return list(directory_path.rglob(f"*{extension}"))
|
|
|
|
|
|
# 使用示例
|
|
python_files = find_files_by_extension(".", ".py")
|
|
print("找到的 Python 文件:")
|
|
for file in python_files:
|
|
print(f" {file}")
|
|
|
|
|
|
# 文件信息获取函数
|
|
def get_file_info(file_path):
|
|
"""获取文件的详细信息"""
|
|
path = Path(file_path)
|
|
if path.exists() and path.is_file():
|
|
stat = path.stat()
|
|
return {
|
|
"name": path.name,
|
|
"size": stat.st_size,
|
|
"modified": stat.st_mtime,
|
|
"absolute_path": str(path.absolute()),
|
|
}
|
|
return None
|
|
|
|
|
|
# 使用示例
|
|
if python_files:
|
|
file_info = get_file_info(python_files[0])
|
|
print(f"文件信息: {file_info}")
|
|
|
|
# 文件备份函数
|
|
import shutil
|
|
|
|
|
|
def create_backup(file_path):
|
|
"""创建文件备份"""
|
|
path = Path(file_path)
|
|
if path.exists() and path.is_file():
|
|
backup_path = path.with_suffix(".bak")
|
|
shutil.copy2(path, backup_path)
|
|
return backup_path
|
|
return None
|
|
|
|
|
|
# 使用示例
|
|
backup_file = create_backup("example.txt")
|
|
if backup_file:
|
|
print(f"备份文件: {backup_file}")
|
|
|
|
# 实用函数优势
|
|
# 模块化:每个函数专注单一功能
|
|
# 可重用:可以在不同项目中重复使用
|
|
# 错误处理:包含适当的错误检查
|
|
# 类型安全:使用 Path 对象提供更好的类型支持
|
|
|
|
# 最佳实践
|
|
# 10.1.路径操作原则
|
|
# 使用 pathlib:新项目推荐使用 pathlib,更现代、更直观
|
|
# 路径分隔符:使用 / 或 os.path.join(),避免直接使用 \
|
|
# 路径检查:操作前检查路径是否存在
|
|
# 异常处理:使用 try-except 处理路径操作错误
|
|
# 跨平台兼容:确保代码在不同操作系统上都能正常工作
|
|
|
|
# 10.2.性能优化建议
|
|
# 缓存路径对象:避免重复创建 Path 对象
|
|
# 批量操作:使用 glob 和 rglob 进行批量文件操作
|
|
# 路径规范化:使用 resolve() 获取规范路径
|
|
# 内存管理:及时释放不需要的路径对象
|
|
|
|
# 10.3.安全注意事项
|
|
# 路径验证:验证用户输入的路径
|
|
# 权限检查:确保有足够的文件操作权限
|
|
# 符号链接:注意符号链接可能带来的安全风险
|
|
# 路径遍历:防止路径遍历攻击
|