跳转至

实战项目7:文件管理器

项目概述

使用 Python 实现一个命令行文件管理器,支持目录浏览、文件操作(复制、移动、删除、重命名)、内容搜索和批量处理等功能。这个项目能帮助你深入理解 Python 的文件与目录操作,是巩固标准库使用的绝佳练习。

学习目标

  • 熟练使用 os、shutil、pathlib 等标准库模块
  • 掌握递归遍历目录树的写法
  • 学习命令行交互程序的设计思路
  • 理解异常处理在文件操作中的重要性
  • 了解批量文件处理的实用技巧

功能需求

核心功能

  • 列出当前目录内容(含文件大小、修改时间)
  • 切换目录、查看当前路径
  • 复制、移动、删除文件和目录
  • 创建目录、重命名文件
  • 按名称/扩展名搜索文件
  • 批量重命名(如统一替换扩展名)

项目结构

file_manager/
├── file_manager.py    # 主程序
└── README.md          # 使用说明

代码实现

完整代码(file_manager.py):

import os
import shutil
import time
from pathlib import Path


def fmt_size(size):
    """把字节数格式化为人类可读的形式。"""
    for unit in ("B", "KB", "MB", "GB"):
        if size < 1024:
            return f"{size:.1f} {unit}"
        size /= 1024
    return f"{size:.1f} TB"


def list_dir(path):
    """列出目录内容。"""
    entries = sorted(Path(path).iterdir(),
                     key=lambda p: (p.is_file(), p.name.lower()))
    if not entries:
        print("(空目录)")
        return
    for entry in entries:
        if entry.is_dir():
            print(f"  <DIR>  {entry.name}/")
        else:
            stat = entry.stat()
            mtime = time.strftime("%Y-%m-%d %H:%M",
                                  time.localtime(stat.st_mtime))
            print(f"{fmt_size(stat.st_mtime and stat.st_size):>10}  "
                  f"{mtime}  {entry.name}")


def safe_do(func, *args, **kwargs):
    """统一处理文件操作中的异常。"""
    try:
        func(*args, **kwargs)
        print("操作成功")
    except FileNotFoundError:
        print("错误:路径不存在")
    except PermissionError:
        print("错误:权限不足")
    except OSError as e:
        print(f"错误:{e}")


def search(root, keyword):
    """递归搜索文件名包含 keyword 的文件。"""
    count = 0
    for dirpath, dirnames, filenames in os.walk(root):
        for name in filenames:
            if keyword.lower() in name.lower():
                print(os.path.join(dirpath, name))
                count += 1
                if count >= 50:
                    print("(结果过多,仅显示前 50 条)")
                    return
    print(f"共找到 {count} 个文件")


def batch_rename(folder, old_ext, new_ext):
    """把 folder 下所有 old_ext 文件重命名为 new_ext。"""
    renamed = 0
    for p in Path(folder).glob(f"*{old_ext}"):
        new_name = p.with_suffix(new_ext)
        if not new_name.exists():
            p.rename(new_name)
            renamed += 1
    print(f"共重命名 {renamed} 个文件")


HELP = """
命令列表:
  ls                     列出当前目录
  cd <目录>              切换目录(.. 返回上级)
  pwd                    显示当前路径
  mkdir <名称>           创建目录
  rm <路径>              删除文件或目录
  cp <源> <目标>          复制文件或目录
  mv <源> <目标>          移动/重命名
  find <关键词>           搜索文件
  rename <旧后缀> <新后缀>  批量重命名
  help                   显示帮助
  exit                   退出
"""


def main():
    cwd = os.getcwd()
    print("Python 文件管理器(输入 help 查看命令)")
    while True:
        cmd = input(f"\n{cwd}> ").strip()
        if not cmd:
            continue
        parts = cmd.split()
        action, args = parts[0], parts[1:]

        if action == "exit":
            print("再见!")
            break
        elif action == "help":
            print(HELP)
        elif action == "ls":
            list_dir(cwd)
        elif action == "pwd":
            print(cwd)
        elif action == "cd" and args:
            target = os.path.abspath(os.path.join(cwd, args[0]))
            if os.path.isdir(target):
                cwd = target
            else:
                print("错误:目录不存在")
        elif action == "mkdir" and args:
            safe_do(os.makedirs, os.path.join(cwd, args[0]), exist_ok=True)
            print("目录已创建")
        elif action == "rm" and args:
            target = os.path.join(cwd, args[0])
            if os.path.isdir(target):
                confirm = input(f"确认删除目录 {target} 及其全部内容?(y/N) ")
                if confirm.lower() == "y":
                    safe_do(shutil.rmtree, target)
            else:
                safe_do(os.remove, target)
        elif action == "cp" and len(args) == 2:
            src, dst = os.path.join(cwd, args[0]), os.path.join(cwd, args[1])
            if os.path.isdir(src):
                safe_do(shutil.copytree, src, dst)
            else:
                safe_do(shutil.copy2, src, dst)
        elif action == "mv" and len(args) == 2:
            safe_do(shutil.move,
                    os.path.join(cwd, args[0]), os.path.join(cwd, args[1]))
        elif action == "find" and args:
            search(cwd, args[0])
        elif action == "rename" and len(args) == 2:
            batch_rename(cwd, args[0], args[1])
        else:
            print("未知命令,输入 help 查看帮助")


if __name__ == "__main__":
    main()

运行指南

python file_manager.py

示例会话:

C:\Users\demo\Documents> ls
  <DIR>  项目/
   1.2 KB  2024-05-01 10:30  笔记.txt

C:\Users\demo\Documents> find 笔记
C:\Users\demo\Documents\笔记.txt
共找到 1 个文件

扩展功能建议

基础扩展

  • 显示隐藏文件开关
  • 按大小/时间排序选项
  • cat <文件> 查看文本文件内容

进阶扩展

  • 使用 argparse 改造为一次性命令行工具
  • 回收站机制:删除的文件先移动到 .trash 目录
  • 操作日志记录(写入 history.log)

高级扩展

  • 基于 tkinter 或 PyQt 开发图形界面版本
  • 集成 watchdog 库实现目录变化监控
  • 支持压缩包的创建与解压(zipfile、tarfile)

常见问题

Q: 删除目录时为什么需要二次确认?

A: shutil.rmtree 会不可逆地删除整个目录树,二次确认可以防止误操作。实际产品中建议配合回收站机制使用。

Q: Windows 和 Linux 路径有什么区别?

A: 建议始终使用 os.path.join 或 pathlib.Path 拼接路径,它们会自动处理不同操作系统的路径分隔符。

Q: 如何处理文件名乱码?

A: Windows 下部分文件名编码可能异常,可以用 os.fsdecode 做容错解码。

项目总结

本项目实现了一个功能完整的命令行文件管理器,涵盖了:

  1. 文件系统操作:os、shutil、pathlib 的综合运用
  2. 递归遍历:目录树的搜索与处理
  3. 交互设计:REPL 式命令行循环
  4. 异常处理:统一的安全执行封装
  5. 用户体验:确认机制、格式化输出、帮助信息

下一步


祝你开发愉快!