从相机导出的照片、从压缩包里解出的图片、游戏机传过来的截图,最后往往全都躺在同一个文件夹里,几百个文件挤成一团。手动整理这件事,多数人坚持不过三天。系统自带的自动整理规则又太死板,想按文件名里的日期分层建目录,基本无从下手。

用 Python 搭一个「落地文件夹」是更灵活的解法:指定一个目录,任何文件丢进去,脚本立刻识别、改名、按规则挪到该去的位置。关键在于不用笨办法。最原始的思路是写个死循环反复列目录、比对差异,既费电又不及时。Watchdog 这个库直接调用操作系统的原生接口——Linux 上是 inotify,macOS 上是 FSEvents——由系统在文件变化时主动通知程序。
一、先把环境搭好
How-To Geek 撰稿人 Bobby Jack 强调,虚拟环境这一步别省,否则后面会后悔:
mkdir my-project
cd my-project
python3 -m venv venv
source venv/bin/activate
Windows 下激活命令换成 venv\Scripts\activate。然后安装库:
python -m pip install watchdog
二、跑通最小示例
先别管细节,把下面这段跑起来,确认监听有效:
import time
import logging
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
event_handler = LoggingEventHandler()
observer = Observer()
observer.schedule(event_handler, '.', recursive=True)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
运行后它会盯住当前目录。此时新建一个空文件,或者把某个文件改名,控制台就会打印出对应的事件日志。
三、按文件名里的日期自动分层
Bobby Jack 的实际需求是整理游戏机截图。这类文件名形如 2025010409204300-D796833F72011BDFC9868896D061B51F.jpg,前 14 位依次是年、月、日、时、分、秒,接着两位用于区分同一秒内的多张,短横线后是 32 位十六进制的软件标识,扩展名固定为 .jpg(同一批里的 .mp4 视频直接忽略)。目标是把它们整理成「年/月/日」的目录结构。
先定义好三个常量和一条正则表达式,括号里的捕获组分别对应年、月、日和剩余部分:
import os
import time
import re
from pathlib import Path
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
WATCH_FOLDER = Path("/tmp")
TARGET_FOLDER = Path("/Users/bobby/Pictures/switch-screenshots")
PATTERN = r"^([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{8}-[A-F0-9]{32}\.jpg)$"
处理逻辑写在事件处理类里,覆盖父类的 on_created 方法:
class FileDropHandler(FileSystemEventHandler):
def on_created(self, event):
if event.is_directory:
return
file_path = Path(event.src_path)
if not re.match(PATTERN, file_path.name):
return
self._wait_for_file_copy(file_path)
self.process_file(file_path)
def process_file(self, file_path):
try:
search = re.search(PATTERN, file_path.name)
if not search:
return
target = TARGET_FOLDER / search.group(1)
target = target / search.group(2)
target = target / search.group(3)
target.mkdir(parents=True, exist_ok=True)
file_path.move(target / search.group(4))
print(f"Moved: {file_path.name}")
except Exception as e:
print(f"Error processing {file_path.name}: {e}")
其中 _wait_for_file_copy 是一段用于确认文件已经复制完毕的检查代码,作用是避免在文件还没写完时就去搬动它。主程序部分与前面的示例几乎一致,只是把处理器换成 FileDropHandler(),并把监听路径指向 WATCH_FOLDER。
四、改成自己的规则
监听路径和目标路径目前是写死的,做成命令行参数会更好用。真正需要动的只有那条正则表达式:把它换成自己文件的命名规律,捕获组对应想要的目录层级,整套逻辑就能直接复用。
能识别落地文件并对其做处理之后,可发挥的空间就大了——合并零散笔记、按内容把文档分类、批量把图片缩放到指定尺寸,都只是在这个骨架上多写几行的事。
来源:How-To Geek







