SlothSort:零操作、本機運行的 AI 檔案整理工具
SlothSort 🦥: The Zero-Effort, Local AI File Organizer
SlothSort 是以 Python 編寫的本機 AI 檔案整理工具,透過 Ollama 運行開放權重模型 Llama-3.1,按檔名生成描述性名稱及資料夾分類,並自動移動檔案。檔案存放滿 24 小時後才會處理,資料不會離開用戶的電腦,亦無需支付訂閲費或連接 Wi-Fi。作者表示,首次啟動時工具整理了 Downloads 資料夾內 200 多個檔案。
What I Built
I built SlothSort, a background digital butler that rewards peak laziness.
Like most developers, my Downloads folder is a chaotic graveyard of files named Screenshot_10222026.png, invoice_final_v2_FINAL.pdf, and asdfasdf.jpg. I am simply too lazy to rename and organize them manually.
SlothSort is a lightweight Python agent that monitors your messy folders. Channeling true International Sloth Day energy, it waits exactly 24 hours before acting on any new file. Once a file hits the "sloth threshold," the script wakes up, analyzes the file using a local open-weight model to determine context, generates a clean, descriptive file name, and moves it to a neatly categorized directory (like /Invoices, /Work_Docs, or /Images). You do absolutely nothing while your computer does the housekeeping.
Demo
(Note: I am running this entirely offline via my terminal. The script detects old files on startup, processes them silently through the local LLM, and prints the new mapped destinations.)
SlothSort started. Watching /Users/harsh/Downloads for files older than 24 hours...
SlothSort awakening to process: IMG_9921_rec.jpg
Moved: IMG_9921_rec.jpg -> /Users/dev/Documents/SlothSorted/Images/receipt_scan.jpg
SlothSort awakening to process: Q3_tax_est.pdf
Moved: Q3_tax_est.pdf -> /Users/dev/Documents/SlothSorted/Financials/Q3_tax_estimate.pdf
Code
import os
import time
import shutil
import json
from pathlib import Path
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import ollama
WATCH_DIR = os.path.expanduser("~/Downloads")
BASE_SORT_DIR = os.path.expanduser("~/Documents/SlothSorted")
SLOTH_THRESHOLD_SECONDS = 86400 # 24 hours
class SlothHandler(FileSystemEventHandler):
def process_file(self, file_path):
file_name = os.path.basename(file_path)
# Skip hidden files or already processing files
if file_name.startswith('.'):
return
# Get file age
file_stat = os.stat(file_path)
file_age = time.time() - file_stat.st_mtime
if file_age > SLOTH_THRESHOLD_SECONDS:
print(f"SlothSort awakening to process: {file_name}")
new_name, category = self.ask_local_llm(file_name)
if new_name and category:
self.move_and_rename(file_path, new_name, category)
def ask_local_llm(self, filename):
prompt = f"""
You are a highly efficient file organizer. I have a file named '{filename}'.
Based ONLY on this file name, provide a clean, descriptive file name (keeping the original extension)
and a broad folder category for it (e.g., Invoices, Images, Documents, Installers, Code).
Respond ONLY in strict JSON format like this: {{"new_name": "clean_name.ext", "category": "CategoryName"}}
"""
try:
response = ollama.chat(model='llama3.1', messages=[
{'role': 'user', 'content': prompt}
])
result = json.loads(response['message']['content'])
return result.get('new_name'), result.get('category')
except Exception as e:
print(f"Failed to process {filename} via Ollama: {e}")
return None, None
def move_and_rename(self, old_path, new_name, category):
target_dir = os.path.join(BASE_SORT_DIR, category)
os.makedirs(target_dir, exist_ok=True)
new_path = os.path.join(target_dir, new_name)
# Avoid overwriting existing files
counter = 1
while os.path.exists(new_path):
name, ext = os.path.splitext(new_name)
new_path = os.path.join(target_dir, f"{name}_{counter}{ext}")
counter += 1
shutil.move(old_path, new_path)
print(f"Moved: {os.path.basename(old_path)} -> {new_path}")
def on_modified(self, event):
if not event.is_directory:
self.process_file(event.src_path)
if __name__ == "__main__":
print(f"SlothSort started. Watching {WATCH_DIR} for files older than 24 hours...")
os.makedirs(BASE_SORT_DIR, exist_ok=True)
event_handler = SlothHandler()
observer = Observer()
observer.schedule(event_handler, WATCH_DIR, recursive=False)
observer.start()
# Run an initial scan on startup
for file in os.listdir(WATCH_DIR):
event_handler.process_file(os.path.join(WATCH_DIR, file))
try:
while True:
time.sleep(3600) # Sleep for an hour, peak sloth behavior
except KeyboardInterrupt:
observer.stop()
observer.join()
How I Built It
SlothSort is built entirely on open-source AI and local inference:
The Brain: Llama-3.1 (open-weight model) running completely locally via Ollama. I configured the prompt to force strict JSON outputs containing new_name and category keys.
The Harness: Python utilizing the watchdog library to monitor the file system for changes and track file age (os.stat().st_mtime).
The Workflow: When a file crosses the 24-hour threshold, the script sends the file context to the local Ollama API. Upon receiving the parsed JSON response, shutil safely moves and renames the file into the new structured directory tree, automatically handling any name collisions.
Why Does Open Innovation Matter?
For a personal file-sorting tool, open innovation is non-negotiable due to privacy and cost.
A closed API approach would require me to upload my personal bank statements, medical PDFs, and private photos to a third-party server just to generate a file name. That is an unacceptable privacy risk for basic desktop utility. By utilizing an open-weight model via Ollama, my data physically never leaves my machine.
Additionally, running this locally means I set it up once and never pay a subscription fee or worry about API token limits. Whether I download 10 files or 10,000, open-source AI makes this background automation completely free, private, and capable of running without a Wi-Fi connection.
The Lazy Payoff
The payoff is zero-maintenance organization. I ran the initial startup script today and SlothSort processed over 200 neglected files from my Downloads folder. For the first time in years, my Downloads directory is completely empty, and everything is neatly filed into /Financials, /Project_Assets, and /Random_Junk. It saved me hours of manual renaming and dragging-and-dropping, allowing me to fully embrace the sloth lifestyle this week.
Prize Categories
Open-Weight Champion
Best Local Automation
來源:DEV Community · dev.to