☰
AI File Sorter Headless 无界面集成完全指南:CLI 参数、状态 JSON 与并发锁一次讲清
2026/10/11 16:37:01 网站建设 项目流程
  • AI 应用
  • 大模型
  • 本地部署
  • 桌面应用

【免费下载链接】ai-file-sorter

Cross-platform desktop application for content-aware file organization and renaming. Supports local and remote LLMs, preview-based workflows, and fully user-controlled changes.

项目地址:https://gitcode.com/gh_mirrors/ai/ai-file-sorter
点击查看免费下载

AI File Sorter是一款跨平台、内容感知的智能文件整理工具。本文完整解析它的Headless 无界面集成契约:逐条拆解CLI 命令行参数、机器可读的状态 JSON字段,以及防止多任务互相踩踏的运行时并发锁,帮你在资源管理器扩展或自动化脚本里安全地"无人值守"调用它。

如果你只想把它当 GUI 应用用,那 Headless 模式你可能用不上。但一旦要把它接进 Windows 资源管理器右键、CI 流水线、或你自己的批处理脚本,这套无界面契约就是"稳定接口"——你不需要点开任何窗口,只需要解析一段 JSON。

🧩 什么是 Headless 无界面模式

普通用户双击图标,看到的是主窗口、分类对话框、审查确认面板。而Headless(无界面)模式走的是另一条"中立于 UI"的入口:它不加载任何对话框,只负责

  1. 解析命令行参数;
  2. 抢占一把共享的运行时锁;
  3. 执行与 GUI 完全相同的分析工作流;
  4. 把每一步进度以JSON的形式打印到stdout,并(可选地)写入一个状态文件。

💡 对集成者最重要的认知:把stdout/ 状态文件里的 JSON 当作契约,stderr只当诊断日志。这一条在官方契约文档里被反复强调。

Headless 模式和 GUI 模式共用同一套分析引擎,所以你在 GUI 里看到的"整理前后"效果,命令行里也能 1:1 复现。

🚀 快速开始:一条命令跑通

下面这条命令会对一个文件夹做"分类 + 重命名",把状态写到status.json,并强制走审查流程(只出计划、不真正移动文件):

aifilesorter --headless \ --operation categorize-and-rename \ --path "/home/user/Downloads" \ --status-file "/tmp/aifs/status.json" \ --job-id "demo-001" \ --review-only

跑完后你不会看到任何窗口,但status.json里会记录每一步状态,stdout也会同步打印。想先看"它打算怎么动我的文件",用--review-only就对了。

📋 CLI 参数速查表

完整用法(--headless-help也能打印):

Usage: aifilesorter --headless --operation <categorize|rename|categorize-and-rename> \ --path <file-or-folder> [--path <file-or-folder> ...] \ [--status-file <json-file>] [--job-id <id>] \ [--review-file <json-file>] [--review-only|--auto-apply] \ [--include-subdirectories|--no-include-subdirectories] \ [--settings-overrides-file <json-file>] aifilesorter --headless-apply --review-file <json-file> \ [--status-file <json-file>] [--job-id <id>]
参数作用备注
--headless进入无界面分析模式核心开关
--headless-apply直接应用一份已保存的审查计划不重新跑分析
--headless-help打印用法说明立即退出
--operationcategorize/rename/categorize-and-rename见下节
--path目标文件或文件夹可重复出现多次
--status-file把状态 JSON 额外写到此文件stdout始终会有
--job-id任务标识缺省自动生成
--review-file审查计划 JSON 路径供--headless-apply使用
--review-only只出审查计划,不改文件与--auto-apply二选一
--auto-apply跳过审查,直接应用谨慎使用
--include-subdirectories扫描子文件夹默认关闭
--no-include-subdirectories显式排除子文件夹
--settings-overrides-file注入一次性的设置覆盖(JSON)不写回用户配置

参数值既可以用--key value,也可以写成--key=value的内联形式,两种都能被识别。

三种操作模式

  • categorize:分类并按设置把文件移动到分类文件夹。
  • rename:只应用重命名建议,不移动文件。
  • categorize-and-rename:把上面两种合并成一份可审查的计划。

支持的目标范围

当前契约只接受两种形状:一个文件夹目标;或位于同一个父文件夹里的多个文件。跨文件夹的"搜索结果式"聚合暂不支持(属于后续版本)。传错形状会返回退出码4(不支持)。

🔄 审查与应用:默认"先看后动"

AI File Sorter 的哲学是用户完全掌控每一次变更。Headless 模式继承了这一点,默认不是"静默改写",而是"能出审查计划的工作流":

  • --review-only:强制只准备审查,不动任何文件;
  • --auto-apply:明确选择"直接应用",适合你完全信任结果的自动化场景;
  • 都不传时,跟随应用里保存的设置。

一旦进入审查流程,程序会把计划写成一个审查计划文件(JSON),并在状态里告诉你它的路径(reviewFile)。等你(或你的脚本/界面)确认无误后,再用一条命令把这份计划"原样"应用下去:

aifilesorter --headless-apply \ --review-file "/tmp/aifs/status.review.json" \ --status-file "/tmp/aifs/status.json"

--headless-apply不重新分析,只回放已批准的计划——这让"人在环中(human-in-the-loop)"的审批流变得既安全又可审计。

📄 状态 JSON 完整字段

每次状态更新(running/completed/failed/ …)都会输出一个 JSON 对象。核心字段如下:

{ "schemaVersion": 1, "status": "running", "operation": "categorize-and-rename", "jobId": "headless-1234-1700000000000", "message": "Headless command accepted and runtime lock acquired.", "error": "", "updatedAtUtc": "2026-03-11T17:43:22.123", "runtime": { "gpuBackend": "cuda", "llamaDevice": "cuda", "ggmlDisableCuda": "0" }, "paths": ["/home/user/Downloads"], "lock": { "owner": "headless", "pid": "1234", "jobId": "headless-1234-1700000000000", "startedAtUtc": "2026-03-11T17:43:22.123", "description": "Headless categorize-and-rename" } }

字段速读:

字段含义
schemaVersion状态结构版本,当前恒为1
status稳定状态值(见下表)
operation本次操作(categorize等)
jobId任务标识,可用于关联日志
message/error人类可读的状态 / 错误描述
updatedAtUtc本次更新的时间戳(ISO 8601)
runtimeGPU 后端等运行环境信息(来自环境变量,存在才出现)
paths你传入的目标路径列表
lock当前持有锁的元数据(见"并发锁"一节)

进入"审查 / 应用"阶段后的额外字段

当流程推进到审查或应用时,状态里会追加一份变更明细,供你直接渲染进度条或清单:

{ "status": "review_required", "entryCount": 3, "entries": [ { "source": "/home/user/Downloads/photo1.jpg", "destination": "/home/user/Downloads/Images/20260311_090909.jpg", "fileName": "photo1.jpg", "destinationName": "20260311_090909.jpg", "category": "Images", "subcategory": "", "renameOnly": false, "moved": false, "renamed": false, "skipped": false } ], "movedCount": 0, "renamedCount": 0, "skippedCount": 0, "review": { "entryCount": 3, "requiresApproval": true, "entries": [ "…" ] }, "apply": { "movedCount": 0, "renamedCount": 0, "skippedCount": 0, "undoPlanSaved": false }, "reviewRequired": true, "reviewFile": "/tmp/aifs/status.review.json" }

注意running阶段的更新里也可能夹带部分审查预览条目,让你在任务还没跑完时就能先展示"已出的中间结果"。

🚦 稳定状态值 与 退出码

status值什么时候出现
running任务接受、正在分析
review_required已生成审查计划,等待批准
completed全部成功完成
failed通用失败
cancelled被停止标记取消
blocked被锁占用 / 缺 LLM 等前置条件挡住

进程退出码则用于脚本判断:

退出码常量含义
0Success成功
1Failure执行失败 / 被取消
2Usage参数错误、用法不对
3Busy运行时锁被占用,无法执行
4Unsupported目标形状不被支持

两个高频的blocked场景值得单独记一下:

① 锁被占用(另一个任务正在跑,退出码3):

{ "status": "blocked", "message": "Another analysis job is already running.", "lock": { "owner": "explorerWorker", "jobId": "explorer-job" } }

② 还没有选 LLM(需要先去选模型,退出码1)——状态里会带上机器可读的"该做什么"提示:

{ "status": "blocked", "message": "AI File Sorter needs an LLM selection before this Explorer job can run. …", "actionRequired": "select_llm", "actionLabel": "Select LLM" }

看到actionRequired: "select_llm"时,你的界面就知道该弹出"选择 LLM"入口了。

🔐 并发锁:AnalysisRuntimeLock

这是整篇里最容易被低估、也最关键的一节。GUI、资源管理器 Worker、Headless 三种入口共享同一把锁,保证同一时刻只有一个分析/变更任务在动 LLM、缓存和文件。

锁由两个文件构成,都放在"配置目录 /runtime"下:

  • 锁文件analysis-runtime.lock:由操作系统的QLockFile机制持有,真正的互斥主体;
  • 元数据旁挂文件analysis-runtime.lock.json:记录"谁在锁着",供界面展示与过期锁恢复。

元数据长这样:

{ "owner": "headless", "pid": 1234, "jobId": "headless-1234-1700000000000", "startedAtUtc": "2026-03-11T17:43:22.123", "description": "Headless categorize" }

其中owner的取值有gui/explorerWorker/headless三种,方便你一眼看出"现在被谁占着"。

过期锁自动恢复:如果持有锁的进程已经死了(通过pid探活 + 主机名比对判断),下次try_acquire会主动清掉死锁并重试,避免一次崩溃就把整个运行时"锁死"。

⚠️ 给集成者的忠告:不要假设能安全地对同一运行时并发跑多个分析/变更任务。撞上锁就拿到退出码3+status: "blocked",正确姿势是排队或稍后重试,而不是绕过锁。

锁的实现见 AnalysisRuntimeLock.cpp,头文件里的Lease用 RAII 保证"拿到就释放、异常也释放",见 AnalysisRuntimeLock.hpp。

🛑 如何中途停止任务

如果任务在--status-file指定了状态文件,那么在状态文件旁创建一个同名的.stop标记文件即可请求停止。程序每 250ms 轮询一次这个标记,一旦发现就请求工作流停止,最终状态变为cancelled。

# 假设状态文件是 /tmp/aifs/status.json touch /tmp/aifs/status.json.stop # 发出"停止"信号

这让"长任务可中断"在无人值守场景下也成了可能。

⚙️ 一次性设置覆盖(不改用户配置)

Headless 调用方经常想"这次用点不一样的行为",但不想污染用户已保存的设置。--settings-overrides-file就是干这个的:传入一个 JSON,它只对当前这一次运行生效,运行结束即丢弃,绝不写回配置。

字段都是"可选"的——不写的保持原样,写了的就覆盖本次运行。常用字段示例:

{ "useSubcategories": true, "includeSubdirectories": true, "allowedCategories": ["Images", "Documents", "Software"], "categoryLanguage": "en" }

完整可覆盖的字段清单(分类/子分类、白名单、图片/文档按内容分析、是否仅重命名、语言等)见 HeadlessSettingsOverrides.hpp。这一机制是"集成专属行为"的推荐方式,官方配置文档也特别点名,见配置与环境。

🗂️ 典型集成场景

场景 A:资源管理器右键"一键整理"先--headless --review-only生成计划 → 把entries渲染成确认框 → 用户点头后--headless-apply应用。全程无人值守,且每一步都可审计。

场景 B:CI / 定时批处理加--auto-apply直接应用,用退出码0/1/2/3/4决定脚本是重试、告警还是跳过。缺 LLM 时读到actionRequired后发出"请配置 LLM"的工单即可。

场景 C:防冲突的并发调度用status.lock.owner和退出码3判断"是否有人在跑",把多个来源的任务天然串行化,不需要自己再造锁。

🔍 相关文件与源码索引

想深入源码时,按下面这些入口读最快:

  • 契约总览:docs/headless-runtime-contract.md
  • 命令解析与执行:HeadlessAnalysisCommand.cpp(ExitCode定义见 HeadlessAnalysisCommand.hpp)
  • 状态 JSON 生成:HeadlessStatusJson.cpp
  • 运行时锁:AnalysisRuntimeLock.cpp
  • 设置覆盖字段:HeadlessSettingsOverrides.hpp
  • Headless 入口分发:main.cpp

一句话总结:Headless 模式 = 一条 CLI 命令 + 一份状态 JSON + 一把共享锁。把它当"稳定接口"来用——stdout/状态文件是契约、--review-only保证先看后动、退出码3提示你排队——你就能在资源管理器扩展或自动化脚本里,安全、可审计地把 AI File Sorter 的能力接进自己的产品。

  • AI 应用
  • 大模型
  • 本地部署
  • 桌面应用

【免费下载链接】ai-file-sorter

Cross-platform desktop application for content-aware file organization and renaming. Supports local and remote LLMs, preview-based workflows, and fully user-controlled changes.

项目地址:https://gitcode.com/gh_mirrors/ai/ai-file-sorter
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询