从需求到变现:我用 24 小时做了一个文件整理工具

5 阅读2分钟

前言

作为一个程序员,我的 Downloads 文件夹常年处于"核爆"状态:

  • 截图、文档、安装包混在一起
  • 文件名乱码、重名、找不到
  • 每次想整理都无从下手

于是,我决定花一天时间做个工具解决这个问题。

需求分析

核心需求很简单:

  1. 识别文件类型
  2. 按类型分类
  3. 按日期归档
  4. 智能命名

技术实现

1. 文件类型识别

使用文件扩展名 + MIME 类型双重识别:

FILE_CATEGORIES = {
    'Images': ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg', '.ico', '.bmp'],
    'Documents': ['.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.txt', '.md'],
    'Videos': ['.mp4', '.avi', '.mov', '.mkv', '.flv', '.wmv'],
    'Audio': ['.mp3', '.wav', '.flac', '.aac', '.m4a'],
    'Archives': ['.zip', '.rar', '.7z', '.tar', '.gz'],
    'Code': ['.py', '.js', '.ts', '.html', '.css', '.json', '.xml', '.yml'],
    'Executables': ['.dmg', '.exe', '.pkg', '.app'],
    'Spreadsheets': ['.xls', '.xlsx', '.csv', '.numbers'],
}

2. 分类逻辑

def categorize_file(filename):
    ext = Path(filename).suffix.lower()
    for category, extensions in FILE_CATEGORIES.items():
        if ext in extensions:
            return category
    return 'Others'

3. 日期归档

def get_date_folder(file_path):
    mtime = os.path.getmtime(file_path)
    date = datetime.fromtimestamp(mtime)
    return date.strftime('%Y-%m')

4. 智能命名

def clean_filename(filename):
    # 移除特殊字符
    clean = re.sub(r'[^\w\-_\.]', '_', filename)
    # 处理重名
    if os.path.exists(target_path):
        clean = f"{stem}_{counter}{suffix}"
    return clean

效果展示

整理前

Downloads/
├── Screenshot 2024-03-15 at 10.23.45 AM.png
├── 未命名文档.docx
├── 腾讯会议-20240315-录音.mp3
├── install-latest-stable.dmg
└── ...(还有 100+ 文件)

整理后

Downloads/
├── Images/
   └── 2024-03/
       └── Screenshot_2024-03-15_10_23_45.png
├── Documents/
   └── 2024-03/
       └── 未命名文档.docx
├── Audio/
   └── 2024-03/
       └── 腾讯会议-20240315-录音.mp3
├── Executables/
   └── 2024-03/
       └── install-latest-stable.dmg

变现验证

我做了一个决定:把这个工具商业化。

  • 定价:¥19 永久
  • 平台:Gumroad(支持支付宝/微信)
  • 网站:ipipq.com

这不是什么复杂的技术,但解决了真实痛点。

小结

  1. 先解决问题:从自己的痛点出发
  2. 快速实现:一天完成核心功能
  3. 验证市场:直接上架售卖

与其纠结技术方案,不如先做出来。


🔗 工具地址:ipipq.com

如果你也有文件整理的烦恼,欢迎试试。