OpenCode 实践课:3 分钟用 Python 写出一个命令行文件批量重命名工具

项目介绍

照片、文档、下载文件散落一堆,想统一加前缀、替换关键字、按序号整理?手动一个个改名太痛苦。

今天我们让 OpenCode 帮我们写一个命令行文件批量重命名工具,支持:

  • 批量添加前缀/后缀
  • 文字查找替换
  • 按序号自动编号(001_xxx)
  • 大小写转换
  • 正则过滤目标文件
  • --dry-run 预览模式(安全第一)

纯 Python 标准库,零依赖,最终代码约 80 行。

准备工作

  • Python 3.7+
  • 安装 OpenCode:参考 opencode.ai 官方文档
  • 配置好 API Key 后终端输入 opencode 即可进入交互界面

实践过程

第一步:写出需求,让 OpenCode 生成代码

我直接在 OpenCode 中用自然语言描述需求:

> 我对 OpenCode 说:
>
> 用 Python 写一个命令行文件批量重命名工具,支持:添加前缀(-p)、后缀(-s)、文本替换(-r old:new)、序号重命名(-n)、大小写转换(-c upper/lower)、正则过滤(-f)、预览模式(--dry-run)。纯标准库,约 80 行。

OpenCode 立刻开始分析需求,几秒后生成了完整代码。它自动将功能拆分为 rename_files() 核心函数和 main() 命令行入口,用 argparse 解析参数,结构清晰。

第二步:检查并测试预览模式

> 我对 OpenCode 说:
>
> 帮我创建测试文件,然后测试 --dry-run 预览功能。

OpenCode 执行了以下操作:

mkdir /tmp/test_rename && cd /tmp/test_rename
touch report_2024.pdf 照片_001.jpg photo_002.png README.md
python rename.py . --dry-run -r "photo:image" --numbering

输出预览:

[预览] README.md -> 001_README.md
[预览] photo_002.png -> 002_image_002.png
[预览] report_2024.pdf -> 003_report_2024.pdf
[预览] 照片_001.jpg -> 004_照片_001.jpg

关键要点--dry-run 模式在实际操作前预览所有变更,避免误操作。这是用自然语言和 AI 协作的一大优势——你可以一边描述功能,一边即时验证。

第三步:实际执行并验证结果

> 我对 OpenCode 说:
>
> 执行真实重命名,把所有文件改成 project_ 前缀 + 序号。

OpenCode 运行了:

python rename.py /tmp/test_rename -p "project_" --numbering

输出:

重命名: README.md -> 001_project_README.md
重命名: photo_002.png -> 002_project_photo_002.png
重命名: report_2024.pdf -> 003_project_report_2024.pdf
重命名: 照片_001.jpg -> 004_project_照片_001.jpg
完成: 处理了 4 个文件

整个过程我只用3 句自然语言就完成了开发、测试、执行,没有手写一行代码。

完整代码

#!/usr/bin/env python3
"""文件批量重命名工具 — 全文用 OpenCode 生成"""

import os
import sys
import argparse
import re


def rename_files(directory, pattern=None, prefix=None, suffix=None,
                 replace=None, numbering=False, case=None, dry_run=False):
    if not os.path.isdir(directory):
        print(f"错误: 目录 '{directory}' 不存在")
        return

    files = sorted([
        f for f in os.listdir(directory)
        if os.path.isfile(os.path.join(directory, f))
    ])

    if pattern:
        regex = re.compile(pattern)
        files = [f for f in files if regex.search(f)]

    if not files:
        print("没有找到匹配的文件")
        return

    renamed = 0
    for idx, old_name in enumerate(files, 1):
        name, ext = os.path.splitext(old_name)
        new_name = name

        if replace:
            old_str, new_str = replace.split(":", 1) if ":" in replace else (replace, "")
            new_name = new_name.replace(old_str, new_str)

        if prefix:
            new_name = prefix + new_name
        if suffix:
            new_name = new_name + suffix
        if numbering:
            new_name = f"{idx:03d}_{new_name}"
        if case == "upper":
            new_name = new_name.upper()
        elif case == "lower":
            new_name = new_name.lower()

        new_name += ext

        if new_name == old_name:
            continue

        old_path = os.path.join(directory, old_name)
        new_path = os.path.join(directory, new_name)

        if os.path.exists(new_path) and not dry_run:
            print(f"跳过: {old_name} -> {new_name} (目标已存在)")
            continue

        if dry_run:
            print(f"[预览] {old_name} -> {new_name}")
        else:
            os.rename(old_path, new_path)
            print(f"重命名: {old_name} -> {new_name}")
        renamed += 1

    action = "预览" if dry_run else "完成"
    print(f"\n{action}: 处理了 {renamed} 个文件")


def main():
    parser = argparse.ArgumentParser(description="文件批量重命名工具")
    parser.add_argument("directory", help="目标目录路径")
    parser.add_argument("-p", "--prefix", help="添加文件名前缀")
    parser.add_argument("-s", "--suffix", help="添加文件名后缀")
    parser.add_argument("-r", "--replace", help="替换文本, 格式: old:new")
    parser.add_argument("-n", "--numbering", action="store_true",
                        help="按序号重命名 (001_文件名)")
    parser.add_argument("-c", "--case", choices=["upper", "lower"],
                        help="转换大小写")
    parser.add_argument("-f", "--filter", help="正则过滤文件名")
    parser.add_argument("--dry-run", action="store_true",
                        help="预览模式, 不实际执行")
    args = parser.parse_args()

    rename_files(
        directory=args.directory, pattern=args.filter,
        prefix=args.prefix, suffix=args.suffix, replace=args.replace,
        numbering=args.numbering, case=args.case, dry_run=args.dry_run,
    )


if __name__ == "__main__":
    main()

小结

用 OpenCode 开发这个小工具,我从"想做一个文件重命名工具"到"在终端跑起来验证",只花了 3 分钟

传统开发流程:查 argparse 文档、写参数解析、写文件遍历逻辑、处理边界条件、写测试用例——即使熟练也要 20-30 分钟。而 OpenCode 让我把注意力集中在描述需求上,细节全部交给 AI。

几个体会:

先预览再执行:让 AI 加上 --dry-run 模式,是"零成本"的安全保障。

对话式迭代:第一版代码不满意?直接说"把文件按修改时间排序"或"跳过隐藏文件",OpenCode 当场改。

验证很重要:AI 生成的代码也需要跑一遍,别盲目信任——但这个过程你自己控制节奏。

命令行小工具是 OpenCode 的绝佳应用场景——逻辑清晰、规模可控、产出立即可用。下次整理文件时,试试让 AI 帮你写一个吧。