How I Used AI and Bash to Organize and Declutter My Mac
A practical walkthrough of automating Downloads, Documents, and Desktop cleanup with zsh, including the macOS shell gotcha that broke it on the first try
In every Mac has three folders: Downloads, Documents, and Desktop. I had a lot of files — meeting recordings, screenshots, PDFs, half-finished project folders, and zip files. I didn’t want to spend time doing the regular tasks of organsizing files into folders by myself. So I asked an AI assistant to help me write a script to do the regular tasks. The process ended up teaching me something interesting about macOS itself.
Step 1: Know What You’re Dealing With
Before touching anything, I exported a simple file listing from Terminal:
for d in ~/Downloads ~/Documents ~/Desktop; do
echo "=== $d ==="
find "$d" -maxdepth 2 -type f -exec stat -f "%N | %z bytes | %Sm" {} \;
done > ~/Desktop/file_listing.txtThis gave a full inventory of file paths, sizes, and modification dates without me having to check all the three separate folders. Turning this into numbers was comfortable to review.
You will end with the three folder files sizes.
Step 2: Don’t Touch the Sensitive Stuff
Buried in the mix were files are secret files.
Any organizing script needs a hard rule here: never move, rename, or touch anything that looks like a secret (credential). Not into a “sensitive” folder, not anywhere, just leave it exactly where it is and flag it in a report so a human can deal with it properly (ideally by importing it into a password manager and deleting the original).
The detection logic ended up being a simple pattern match:
if [[ "$ext" == "ovpn" || "$ext" == "pem" || "$ext" == "key" \
|| "$lower_base" == *"password"* || "$lower_base" == *"secret"* \
|| "$lower_base" == *"recovery"* ]]; then
echo "[SKIPPED - sensitive, left in place] '$base'"
continue
fiNo exceptions, just skip and move on.
Step 3: The Bug That Taught Me About macOS’s Ancient Shell
The first version of the script was written in bash, and it used an associative array to count how many files landed in each category:
declare -A category_countsRan it on macOS. Instant failure:
./organize_mac_folder.sh: line 73: declare: -A: invalid optionHere’s the thing most people don’t know: macOS still ships bash 3.2 by default — a version from 2007. Apple froze it there over a licensing dispute (bash 4+ switched to GPLv3) and never looked back. Associative arrays didn’t arrive until bash 4.0. So any script written assuming a modern bash will quietly break on a stock Mac.
There’s a second, sneakier bug hiding in old bash too: versions before 4.4 throw false unbound variable errors when you expand an empty array under strict mode (set -u). So even after fixing the associative array, a completely empty folder would crash the script.
Get Akarsh Seggemu, M.Sc.’s stories in your inbox
Join Medium for free to get updates from this writer.
The real fix wasn’t patching around bash 3.2 — it was asking the obvious question: why use bash at all? macOS has defaulted to zsh since Catalina in 2019, and it’s a genuinely modern shell (5.8+) with real associative arrays and none of these landmines. Rewriting the script natively in zsh made the workarounds unnecessary:
typeset -A category_counts # just worksLesson: when you’re scripting for macOS, target the shell macOS actually runs today, not the one it’s contractually stuck shipping.
Step 4: The Sorting Logic
With the right shell in place, the actual organizing logic is refreshingly simple. Two rules:
- Loose files at the top level get sorted into category folders by type —
Screenshots,PDFs,Images,Office Docs,Code & Configs,Archives,Videos,Misc. - Existing subfolders — the ones I’d already grouped myself, like a project folder or a notes directory — get moved as a whole unit into a
Project Foldersbucket. Nothing inside them gets reshuffled. The script respects organization I'd already done.
And critically, it defaults to a dry run. Nothing moves until you explicitly pass --apply:
./organize_mac_folder.zsh ~/Downloads # preview only
./organize_mac_folder.zsh ~/Downloads --apply # actually move filesEvery dry run prints exactly what would happen, file by file, so you can sanity-check before committing.
Step 5: Bringing It All Together
Running the script separately on Downloads, Documents, and Desktop leaves you with three different Screenshots folders, three PDFs folders, and so on — better than chaos, but still scattered across three locations.
The last piece was a consolidation script that merges all matching category folders into a single home, ~/Documents/Sorted:
~/Documents/Sorted/Screenshots ← merged from Downloads, Desktop, Documents
~/Documents/Sorted/PDFs ← merged from all three
~/Documents/Sorted/Project Folders
...The only tricky part is name collisions, what if Downloads/Screenshots/shot1.png and Desktop/Screenshots/shot1.png both exist? The script handles it automatically by tagging the later file with its source:
Sorted/Screenshots/shot1.png
Sorted/Screenshots/shot1.png_from_DesktopNothing gets silently overwritten. Empty folders left behind get cleaned up. Sensitive files, once again, are never part of the equation — they were excluded from the start.
What I Ended Up With
- One clean, predictable structure in
~/Documents/Sorted, sorted by file type - A lot of files that were previously invisible due to clutter are now visible and quantified
- Secrets are flagged for manual review instead of being auto-filed somewhere risky
- A script that’s safe to re-run any time new clutter piles up, since it’s idempotent by design
Takeaways if You Want to Try This Yourself
- Measure before you organize. A quick
find+statexport turns the three folders into actual numbers that you can act on. - Treat secrets as untouchable, not just handle carefully. The safest folder for a password export is no folder but a password manager.
- Default to dry-run. Any script that moves files on your behalf should show you the plan before doing anything irreversible.
- Know your shell. If you’re scripting for macOS, remember it defaults to zsh, not the bash your muscle memory might reach for and Apple’s bash 3.2 will bite you in ways that look like bugs in your own logic.
The whole thing consist of three scripts,
- inventory script
- sort script
- consolidation script
it took less time to build and test than it would have taken to manually drag and drop files from various folders. And unlike a one time cleanup, it’s something that I can just run again any time.
Have your own Mac clutter horror story? I’d love to hear what’s hiding in your folders.
If you like my articles, please follow me on Medium, you can also watch my videos on YouTube and you can also support me by buying me a coffee.







