跳转到内容

用 Python 处理一次真实的小事

这一页做一件真事:把一个文件夹里以日期开头的文件按年份分到子文件夹。二十行代码,全部在练习场里跑,先预览再动手。做完这一次,AI 给你的任何小工具你都知道怎么安全地试。

Run it in the sandbox first. Preview before you move anything. Never point a script at real files until it has proven itself on fake ones.Pruébalo primero en el área de prácticas. Previsualiza antes de mover nada. No apuntes un script a archivos reales hasta que haya funcionado con los falsos.

先预览,再动手 建练习场 假文件,随便折腾 DRY_RUN = True 只打印清单 看清单 数量 · 去向 DRY_RUN = False 真的移动 验证 ls · 访达 清单不对就改脚本,再预览 正式资料:先备份,再改路径,仍然先预览 没读过的代码不运行
一个好的脚本重复跑不会出事

必须掌握

  1. 只在练习场跑。 正式资料一个文件都不碰,直到脚本在假文件上跑对了。
  2. 先预览,再动手。 脚本先只打印「将要做什么」,你看过清单,再让它真做。
  3. 有备份。 真跑之前,正式资料做一次时间机器备份。
  4. 不运行没读过的代码。 三十行读不懂,让 AI 逐段加注释,见上一页。

知道即可

Mac 本身不带,但输入 python3 会引导你装命令行开发者工具,装完就有。打开终端,输入:

终端窗口
python3 --version

出现 Python 3.x.x 就有。如果弹出窗口问要不要安装「命令行开发者工具」,点安装,等几分钟再试一次,终端一章有说明。终端怎么用也在那一章。

必须掌握

把这一行整个复制进终端,按 Enter。它在「下载」里建一个「练习场」文件夹,放九个假发票和一个杂物文件,然后用访达打开:

终端窗口
mkdir -p ~/Downloads/练习场 && cd ~/Downloads/练习场 && for y in 2024 2025 2026; do for i in 1 2 3; do echo "假发票" > "${y}-0${i}-15_发票_00${i}.pdf"; done; done && echo "杂物" > "备忘.txt" && open .

这些「pdf」里只有一行字,不是真的 PDF,够练习用。

用什么写脚本:一个纯文本编辑器

Section titled “用什么写脚本:一个纯文本编辑器”

必须掌握

你什么时候会遇到这个问题:你用「文本编辑」写了脚本,运行报 SyntaxError,怎么看都没错。

为什么:「文本编辑」默认是富文本,存出来的文件带着格式;它还会把英文引号 " 自动换成弯引号 “,程序认不出来。脚本、Markdown、CSV 都需要「只存字、不存格式」的纯文本(plain text)。

最简单可靠的做法:装一个纯文本编辑器。我推荐 CotEditor:免费,App Store 直接装,中文界面,打开就能用。它有行号、语法高亮、能显示空格和缩进,Windows 来的 GBK 编码文件也不乱码。它只做这一件事,所以不会吓人。

没装的时候,「文本编辑」也能用:新建文件后,「格式」菜单,「制作纯文本」;再到「文本编辑」的设置里关掉「智能引号」。

VS Code 是以后的事。等你开始用 Claude Code、Cursor 这类 AI 编程工具时再装,它们住在那里。

必须掌握

在练习场里新建一个文本文件,名字叫 整理发票.py,内容照抄进纯文本编辑器。

# 整理发票.py
# 把练习场里名字以年份开头的文件,按年份分到子文件夹
from pathlib import Path
import shutil
FOLDER = Path.home() / "Downloads" / "练习场" # 输入:只看这个文件夹
DRY_RUN = True # True = 只预览,不动文件
for f in sorted(FOLDER.iterdir()): # 重复:对每一个东西
if not f.is_file(): # 条件:文件夹跳过
continue
year = f.name[:4] # 处理:名字前四位当年份
if not year.isdigit(): # 条件:不是年份开头的跳过
print("跳过(名字不以年份开头):", f.name)
continue
target = FOLDER / year / f.name # 输出:年份文件夹 / 原名
if target.exists():
print("已存在,跳过:", f.name)
continue
print("将移动" if DRY_RUN else "移动", f.name, "->", year + "/")
if not DRY_RUN:
target.parent.mkdir(exist_ok=True)
shutil.move(str(f), str(target))

读一遍:输入是练习场这个文件夹,处理是看名字前四位,输出是年份子文件夹。DRY_RUN = True 的时候,最后两行不会执行,它只报告。脚本自己的名字不以数字开头,会被跳过。

必须掌握

终端里:

终端窗口
cd ~/Downloads/练习场
python3 整理发票.py

你会看到一份清单:九个「将移动」,两个「跳过」。多一个 .DS_Store 的跳过也正常,那是访达自己放的隐藏文件。这就是预览。 看清单:数量对吗,去向对吗,有没有不该动的被列进去了?

这一步对了,什么都还没发生。不对,改脚本,再预览。

必须掌握

把脚本里的 DRY_RUN = True 改成 DRY_RUN = False,保存,再运行一次同样的命令。

然后验证,不看它说什么,看结果:

终端窗口
ls
ls 2026

或者在访达里看。三个年份文件夹,各三个文件,备忘.txt 和脚本还在原地。

再运行一次脚本,应该全是「跳过」,因为没有东西可移了。一个好的脚本重复跑不会出事。

练完把整个练习场拖进废纸篓。

必须掌握

错误信息的读法在上一页:最后一行是原因。这个脚本最常见的三个:

  • FileNotFoundError:练习场不存在,或者你没先 cd 进去。回到「建练习场」那一步。
  • SyntaxError 或 IndentationError:复制时缩进乱了,或者用了中文引号。重新复制整段。
  • python3: command not found:命令行开发者工具没装上,或者装到一半。回到「有没有 Python」再走一遍。

看不懂的整段复制给 AI,先让它解释,不让它改。

必须掌握

以后让 AI 写类似的工具,六句话交代之外,多加四条要求:

  1. 「加一个 DRY_RUN 开关,默认只预览。」
  2. 「每处理一个文件打印一行它做了什么。」
  3. 「遇到不认识的文件跳过,不要删任何东西。」
  4. 「每一段加注释。」

拿到代码,按三问读一遍,在练习场跑预览,看清单,再动手。真要用在正式资料上,先备份,再把 FOLDER 改成正式路径,仍然先预览。

知道即可

同一个骨架,换掉「处理」那几行,就是另一件事:

  • 给一批文件名加日期前缀。
  • 把一个 CSV 里的行按某一列分到几个文件。
  • 找出两个文件夹里重名的文件。
  • 把一堆扫描件按案号归类。

每一件都让 AI 写,每一件都先预览。你不需要自己会写,需要的是会读、会试、会拦。

把 DRY_RUN 改回 True,再把 year = f.name[:4] 改成 year = f.name[:7],运行预览,看清单变成了什么。改回去。这一次你改了程序的一行,而且知道它会导致什么。