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
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...)
Install
sudo apt install inotify-tools -y
curl -fsSL https://raw.githubusercontent.com/kushal1o1/haul/main/install.sh | bash
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)
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
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
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)
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.
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 . :)
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!
thanks :) ,glad you like it !