DEV Community

Cover image for Haul :) a tiny file organizer daemon for Linux
KUSHAL BARAL
KUSHAL BARAL

Posted on

Haul :) a tiny file organizer daemon for Linux

I hate messy Downloads folders. You know the feeling:

report.pdf
report(1).pdf
report(2).pdf
screenshot.png
screenshot(1).png
screenshot(2).png
video_final.mp4
video_final_FINAL.mp4
notes.docx
notes_copy.docx
notes_copy_FINAL(1).docx
Enter fullscreen mode Exit fullscreen mode

At some point you just stop caring and let it rot.

Cron jobs felt overkill — why poll every minute just to watch an empty folder? So I built haul. Drop a file in a watched folder, it moves it to the right place. That's it.

The trick — zero CPU when idle

haul uses inotify, a filesystem event API built into the Linux kernel. Instead of running a loop, it just waits for the kernel to say "hey, a file arrived" — sorts it — then exits. systemd restarts it immediately for the next file.

No polling. No persistent process. Nothing running between events.

file lands
    ↓
kernel fires inotify
    ↓
haul wakes up
    ↓
file sorted → ~/Data/subfolder
    ↓
haul exits
    ↓
systemd restarts it
    ↓
(waiting for next file...)
Enter fullscreen mode Exit fullscreen mode

Install

sudo apt install inotify-tools -y
curl -fsSL https://raw.githubusercontent.com/kushal1o1/haul/main/install.sh | bash
Enter fullscreen mode Exit fullscreen mode

Usage

haul install      set up and start
haul sweep        sort files already sitting in watched folders
haul start/stop   manage the service
haul logs         tail the live log
haul uninstall    remove haul (your ~/Data/ is untouched)
Enter fullscreen mode Exit fullscreen mode

What it sorts

Folder Extensions
PDFs .pdf
Images .jpg .jpeg .png .gif .webp .svg
Videos .mp4 .mkv .avi .mov .webm
Audio .mp3 .flac .wav .ogg .m4a
Code .py .js .ts .sh .json .yaml .sql
Zips .zip .tar.gz .rar .7z .deb
WordFiles .doc .docx .odt
Excel .xlsx .xls .csv
Others everything else

Screenshots are detected by source folder, not filename — set SCREENSHOTS to wherever your tool saves them.

Fully configurable

Everything — watched folders, destination, subfolder names, extension rules — is just bash variables at the top of ~/.local/bin/haul. Open it in any editor and change what you want.

DATA="$HOME/Files"          # change destination
DOWNLOADS="$HOME/Desktop"   # change watched folder
Enter fullscreen mode Exit fullscreen mode

After editing: haul restart

Duplicate handling

  • Same file arrives again → deleted silently
  • Same name, different content → renamed with a timestamp before moving

Logs

[2024-01-15 14:30:22] MOVED report.pdf → ~/Data/PDFs/
[2024-01-15 14:31:45] DUPLICATE (identical) skipped: report.pdf
[2024-01-15 14:32:10] CONFLICT renamed: notes_20240115_143210.md
Enter fullscreen mode Exit fullscreen mode

Requirements: Linux with systemd, bash 4+, inotify-tools. Tested on Ubuntu 22.04 / 24.04.

Source: github.com/kushal1o1/haul — MIT licensed.

If you've been living with a messy Downloads folder, give haul sweep a try first — it sorts whatever's already there without touching the daemon.

Top comments (4)

Collapse
 
josephj11 profile image
Joe

This is a great idea, but the implementation is one of those things that everybody wants to do their own way. I'm going to look at it to see how inotify works... I have almost all my downloads ask me where to put them, so my Downlaod folder is always mostly empty.

Collapse
 
kushal1o1 profile image
KUSHAL BARAL

Yea ,depends on how we downloads but This is completely configurable as I mentioned in docs and github with procedure .The main idea is to create a Door(folder) ,here I mentioned Screenshots and downloads folder as a door it never stores it just automatically sweeps where ever we wants ,So yea Just drop files in watched folder ,and the rest will handle the where it should be . :)

Collapse
 
jyotii13 profile image
Jyoti poudel

Been using haul for a bit now and it just works. My Downloads folder is actually clean for the first time in years lol. Love that it uses inotify instead of polling, you can tell thought went into keeping it lightweight. The sweep command was a great starting point to clear out the backlog I already had. Nice work!

Collapse
 
kushal1o1 profile image
KUSHAL BARAL

thanks :) ,glad you like it !