python的文件操作

什么是pathlib?

pathlib是Python 3.4引入的一个内置模块,提供了一种面向对象的方式来处理文件系统路径。
核心思想:把路径当作对象,而不是字符串

from pathlib import Path

# 创建Path对象
path = Path('folder/subfolder/file.txt')

# 现在path是一个对象,有各种方法
print(f"路径:{path}")
print(f"类型:{type(path)}")  # <class 'pathlib.PosixPath'> 或 WindowsPath

创建Path对象

基本创建

from pathlib import Path

# 从字符串创建
p1 = Path('folder/file.txt')
p2 = Path('/home/user/documents')  # 绝对路径
p3 = Path('.')  # 当前目录
p4 = Path('..')  # 上级目录

# 创建空路径
p5 = Path()  # 当前目录

特殊路径

from pathlib import Path

# 当前工作目录
current = Path.cwd()
print(f"当前目录:{current}")

# 用户家目录
home = Path.home()
print(f"家目录:{home}")

# 在Windows上:
# Path('C:/Users/Username/Documents')
# 在Linux/Mac上:
# Path('/home/username/Documents')

跨平台路径(最重要的优势!)

from pathlib import Path

# 写法1:用正斜杠(推荐)
path1 = Path('folder/subfolder/file.txt')

# 写法2:用Path对象拼接
path2 = Path('folder') / 'subfolder' / 'file.txt'

# 在Windows上会自动转换为反斜杠
# 在Linux/Mac上保持不变
print(path1)  # Windows: folder\subfolder\file.txt
              # Linux: folder/subfolder/file.txt

路径拼接和分解

使用 /运算符拼接

from pathlib import Path

# 创建基础路径
base = Path('/home/user')

# 使用 / 运算符拼接(最方便!)
documents = base / 'Documents'
file_path = documents / 'report.docx'

print(f"文档路径:{documents}")
print(f"文件路径:{file_path}")

# 可以连续拼接
path = Path('/') / 'usr' / 'local' / 'bin' / 'python'
print(f"Python路径:{path}")

使用 joinpath() 方法

from pathlib import Path

# joinpath() 方法
path = Path('/home/user').joinpath('Documents', 'file.txt')
print(path)

分解路径的各部分

from pathlib import Path

path = Path('/home/user/Documents/report.docx')

# 获取路径的各个部分
print(f"完整路径:{path}")
print(f"父目录:{path.parent}")
print(f"父目录的父目录:{path.parent.parent}")
print(f"文件名(带扩展名):{path.name}")
print(f"文件名(不带扩展名):{path.stem}")
print(f"扩展名:{path.suffix}")
print(f"所有父目录:{list(path.parents)}")
print(f"锚点(根目录):{path.anchor}")
输出示例:
完整路径:/home/user/Documents/report.docx
父目录:/home/user/Documents
父目录的父目录:/home/user
文件名(带扩展名):report.docx
文件名(不带扩展名):report
扩展名:.docx
所有父目录:[PosixPath('/home/user/Documents'), PosixPath('/home/user'), PosixPath('/home'), PosixPath('/')]
锚点(根目录):/

路径检查和判断

检查路径是否存在

from pathlib import Path

path = Path('some_file.txt')

# 检查是否存在
if path.exists():
    print(f"{path} 存在")
else:
    print(f"{path} 不存在")

# 检查是否是文件
if path.is_file():
    print(f"{path} 是文件")

# 检查是否是目录
if path.is_dir():
    print(f"{path} 是目录")

# 检查是否是符号链接
if path.is_symlink():
    print(f"{path} 是符号链接")

# 检查是否是绝对路径
if path.is_absolute():
    print(f"{path} 是绝对路径")
else:
    print(f"{path} 是相对路径")

获取绝对路径

from pathlib import Path

# 相对路径转绝对路径
relative = Path('folder/file.txt')
absolute = relative.resolve()  # 解析为绝对路径
print(f"相对路径:{relative}")
print(f"绝对路径:{absolute}")

# 注意:resolve() 会解析符号链接
# 如果不解析符号链接,用absolute()
abs_path = relative.absolute()

文件和目录操作

创建目录

from pathlib import Path

# 创建单个目录
new_dir = Path('new_folder')
new_dir.mkdir()  # 如果目录已存在会报错
# 解决方法:
new_dir.mkdir(exist_ok=True)  # 存在时不报错

# 创建多级目录
deep_dir = Path('a/b/c/d/e')
deep_dir.mkdir(parents=True, exist_ok=True)  # 自动创建父目录

删除文件和目录

from pathlib import Path

# 删除文件
file_path = Path('temp.txt')
if file_path.exists():
    file_path.unlink()  # 删除文件
    print(f"已删除文件:{file_path}")

# 删除空目录
empty_dir = Path('empty_folder')
if empty_dir.exists() and empty_dir.is_dir():
    empty_dir.rmdir()  # 只能删除空目录
    print(f"已删除目录:{empty_dir}")

# 删除非空目录(需要shutil)
import shutil
non_empty_dir = Path('non_empty_folder')
if non_empty_dir.exists():
    shutil.rmtree(non_empty_dir)  # 递归删除
    print(f"已删除非空目录:{non_empty_dir}")

重命名和移动

from pathlib import Path

# 重命名文件
old_file = Path('old_name.txt')
new_file = Path('new_name.txt')

if old_file.exists():
    old_file.rename(new_file)
    print(f"重命名:{old_file} -> {new_file}")

# 移动文件(实际是重命名到不同路径)
source = Path('source_folder/file.txt')
target = Path('target_folder/file.txt')

# 确保目标目录存在
target.parent.mkdir(parents=True, exist_ok=True)

if source.exists():
    source.rename(target)
    print(f"移动文件:{source} -> {target}")

文件内容读写

读写文本文件

from pathlib import Path

# 写入文本文件
file_path = Path('example.txt')

# 写入内容(覆盖)
file_path.write_text("Hello, World!\n你好,世界!", encoding='utf-8')

# 追加内容
with file_path.open('a', encoding='utf-8') as f:
    f.write("\n这是追加的内容")

# 读取内容
content = file_path.read_text(encoding='utf-8')
print("文件内容:")
print(content)

# 按行读取
lines = file_path.read_text(encoding='utf-8').splitlines()
for i, line in enumerate(lines, 1):
    print(f"第{i}行:{line}")

读写二进制文件

from pathlib import Path

# 写入二进制文件
data = b'Binary data: \x00\x01\x02\x03'
file_path = Path('data.bin')

file_path.write_bytes(data)

# 读取二进制文件
read_data = file_path.read_bytes()
print(f"读取的数据:{read_data}")

使用open()方法

from pathlib import Path

file_path = Path('data.txt')

# 像内置open一样使用
with file_path.open('w', encoding='utf-8') as f:
    f.write("使用open方法写入\n")
    f.write("第二行内容\n")

# 读取
with file_path.open('r', encoding='utf-8') as f:
    for line in f:
        print(f"读取:{line.strip()}")

遍历目录和文件搜索

遍历目录内容

from pathlib import Path

# 遍历当前目录
current = Path('.')

print("当前目录内容:")
for item in current.iterdir():
    if item.is_file():
        print(f"文件:{item.name}")
    elif item.is_dir():
        print(f"目录:{item.name}")

使用glob模式匹配

from pathlib import Path

# 创建一些测试文件
for i in range(5):
    Path(f'test_{i}.txt').touch()
    Path(f'data_{i}.csv').touch()
Path('image.jpg').touch()
Path('document.pdf').touch()

# 使用glob查找
print("所有.txt文件:")
for txt_file in Path('.').glob('*.txt'):
    print(f"  {txt_file.name}")

print("\n所有.csv文件:")
for csv_file in Path('.').glob('*.csv'):
    print(f"  {csv_file.name}")

# 使用rglob递归查找
print("\n递归查找所有.txt文件:")
for txt_file in Path('.').rglob('*.txt'):
    print(f"  {txt_file}")

更复杂的模式匹配

from pathlib import Path

# 匹配多个模式
for file in Path('.').glob('*.{txt,csv,json}'):
    print(f"文本/数据文件:{file}")

# 匹配特定模式
for file in Path('.').glob('test_?.txt'):  # test_1.txt, test_2.txt等
    print(f"测试文件:{file}")

# 匹配目录
for dir in Path('.').glob('*/'):  # 注意斜杠表示目录
    print(f"子目录:{dir}")

获取文件信息

文件属性

from pathlib import Path
import datetime

file_path = Path('example.txt')

# 如果文件存在,获取属性
if file_path.exists():
    stat_info = file_path.stat()
    
    print("=== 文件属性 ===")
    print(f"文件大小:{stat_info.st_size} 字节")
    print(f"最后访问时间:{datetime.datetime.fromtimestamp(stat_info.st_atime)}")
    print(f"最后修改时间:{datetime.datetime.fromtimestamp(stat_info.st_mtime)}")
    print(f"创建时间:{datetime.datetime.fromtimestamp(stat_info.st_ctime)}")
    
    # 权限信息
    import stat
    print(f"权限:{oct(stat_info.st_mode)[-3:]}")
    print(f"是否可读:{stat_info.st_mode & stat.S_IRUSR != 0}")
    print(f"是否可写:{stat_info.st_mode & stat.S_IWUSR != 0}")
    print(f"是否可执行:{stat_info.st_mode & stat.S_IXUSR != 0}")

文件所有者

from pathlib import Path
import pwd  # Unix系统
import grp  # Unix系统

file_path = Path('example.txt')

if file_path.exists():
    stat_info = file_path.stat()
    
    # 获取所有者信息(Unix系统)
    try:
        owner = pwd.getpwuid(stat_info.st_uid).pw_name
        group = grp.getgrgid(stat_info.st_gid).gr_name
        print(f"所有者:{owner}:{group}")
    except (ImportError, KeyError):
        # Windows系统或无法获取
        print(f"用户ID:{stat_info.st_uid}")
        print(f"组ID:{stat_info.st_gid}")

实际应用示例

示例1:整理下载文件夹

from pathlib import Path
import shutil

def organize_downloads():
    """整理下载文件夹,按类型分类"""
    download_folder = Path.home() / 'Downloads'
    categories = {
        '图片': ['.jpg', '.jpeg', '.png', '.gif', '.bmp'],
        '文档': ['.pdf', '.docx', '.doc', '.txt', '.md'],
        '压缩包': ['.zip', '.rar', '.7z', '.tar', '.gz'],
        '程序': ['.exe', '.msi', '.dmg', '.pkg'],
        '视频': ['.mp4', '.avi', '.mov', '.mkv'],
    }
    
    # 创建分类文件夹
    for category in categories:
        (download_folder / category).mkdir(exist_ok=True)
    
    # 整理文件
    moved_count = 0
    for file_path in download_folder.iterdir():
        if file_path.is_file():
            # 根据扩展名分类
            for category, extensions in categories.items():
                if file_path.suffix.lower() in extensions:
                    target = download_folder / category / file_path.name
                    try:
                        file_path.rename(target)
                        moved_count += 1
                        print(f"移动:{file_path.name} -> {category}/")
                        break
                    except Exception as e:
                        print(f"移动失败 {file_path}: {e}")
    
    print(f"\n整理完成!移动了 {moved_count} 个文件")

# 运行整理
organize_downloads()

示例2:批量重命名文件

from pathlib import Path

def batch_rename(folder, pattern, new_name):
    """
    批量重命名文件
    
    Args:
        folder: 文件夹路径
        pattern: 文件匹配模式,如 '*.jpg'
        new_name: 新文件名模板,如 'image_{index:03d}.jpg'
    """
    folder_path = Path(folder)
    
    if not folder_path.exists():
        print(f"错误:文件夹不存在 {folder}")
        return
    
    # 获取匹配的文件列表
    files = list(folder_path.glob(pattern))
    files.sort()  # 按文件名排序
    
    if not files:
        print(f"没有找到匹配 {pattern} 的文件")
        return
    
    # 批量重命名
    for index, old_path in enumerate(files, 1):
        # 生成新文件名
        new_filename = new_name.format(index=index)
        new_path = folder_path / new_filename
        
        # 重命名
        try:
            old_path.rename(new_path)
            print(f"重命名:{old_path.name} -> {new_filename}")
        except Exception as e:
            print(f"重命名失败 {old_path}: {e}")
    
    print(f"完成!重命名了 {len(files)} 个文件")

# 使用示例:重命名所有jpg图片
batch_rename('/path/to/photos', '*.jpg', 'vacation_{index:03d}.jpg')
示例3:备份重要文件
from pathlib import Path
import shutil
import datetime

def backup_files(source_dir, backup_dir, patterns):
    """
    备份指定类型的文件
    
    Args:
        source_dir: 源目录
        backup_dir: 备份目录
        patterns: 文件匹配模式列表,如 ['*.py', '*.txt']
    """
    source_path = Path(source_dir)
    backup_path = Path(backup_dir)
    
    # 创建带时间戳的备份文件夹
    timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
    backup_folder = backup_path / f'backup_{timestamp}'
    backup_folder.mkdir(parents=True, exist_ok=True)
    
    print(f"开始备份到:{backup_folder}")
    
    copied_count = 0
    # 遍历所有匹配模式
    for pattern in patterns:
        for file_path in source_path.rglob(pattern):
            if file_path.is_file():
                # 保持目录结构
                relative_path = file_path.relative_to(source_path)
                target_path = backup_folder / relative_path
                
                # 创建目标目录
                target_path.parent.mkdir(parents=True, exist_ok=True)
                
                # 复制文件
                try:
                    shutil.copy2(file_path, target_path)  # copy2保留元数据
                    copied_count += 1
                    print(f"备份:{relative_path}")
                except Exception as e:
                    print(f"备份失败 {file_path}: {e}")
    
    print(f"备份完成!共备份 {copied_count} 个文件")

# 使用示例
backup_files(
    source_dir='/path/to/project',
    backup_dir='/path/to/backups',
    patterns=['*.py', '*.txt', '*.md', '*.json']
)

常见问题解答

Q1:什么时候用pathlib,什么时候用os.path?

A:总是用pathlib!除非你维护的是Python 3.4之前的旧代码。
pathlib更现代、更直观
统一了文件系统操作的接口
更好的跨平台支持

Q2:如何判断路径是文件还是目录?

from pathlib import Path

path = Path('some/path')

if path.exists():
    if path.is_file():
        print("是文件")
    elif path.is_dir():
        print("是目录")
else:
    print("路径不存在")

Q3:如何处理路径中的特殊字符?

from pathlib import Path

# pathlib会自动处理特殊字符
path = Path('folder with spaces/file (1).txt')
print(path)  # folder with spaces/file (1).txt

# 但要注意:有些字符是系统保留的
# Windows: < > : " | ? *
# Linux/Mac: / (路径分隔符)

Q4:如何获取文件大小?

from pathlib import Path

path = Path('large_file.zip')
if path.exists():
    size_bytes = path.stat().st_size
    size_mb = size_bytes / (1024 * 1024)
    print(f"文件大小:{size_mb:.2f} MB")

Q5:如何清空目录但不删除目录本身?

from pathlib import Path
import shutil

def clear_directory(dir_path):
    """清空目录内容"""
    dir_path = Path(dir_path)
    
    if dir_path.exists() and dir_path.is_dir():
        # 删除目录内所有内容
        for item in dir_path.iterdir():
            if item.is_file():
                item.unlink()
            elif item.is_dir():
                shutil.rmtree(item)
        print(f"已清空目录:{dir_path}")
    else:
        print(f"目录不存在:{dir_path}")

# 使用
clear_directory('temp_folder')
posted @ 2026-04-23 21:49  MKYC  阅读(32)  评论(0)    收藏  举报