Folder actions on a Mac: let the folder tidy itself
The Downloads folder is the usual reason people go looking for this. Eight hundred items, three copies of the same installer, a handful of invoices that should have been filed in January. Sorting it by hand works exactly once. The next search is for something that files the items as they arrive, and on a Mac the oldest mechanism for that is a Folder Action.
It is worth knowing what that mechanism is and is not, because it has one design rule that decides whether it behaves or runs away, and there are three other tools in the same space that suit different jobs.
What a Folder Action is
Apple's reference defines it directly: Folder Actions is a feature of macOS that associates AppleScript scripts with folders. The script runs when the folder it is attached to has items added or removed, or when its window is opened, closed, moved, or resized.
Five handlers exist, and a script provides whichever one matches the event it cares about:
on adding folder items to this_folder after receiving these_itemson removing folder items from this_folderon opening folder this_folderon closing folder window for this_folderon moving folder window for this_folder from original_coordinates
The first one carries the work in almost every real setup. It receives an alias to the folder and a list of aliases for the items that just arrived, and none of its parameters is optional. The handler is never called directly and returns no value.
Two of the five come with caveats in Apple's own documentation. The moving folder window for handler is marked as not currently available, and a warning notes that Folder Actions does not activate attached scripts of that kind when the folder is moved. Building anything on window geometry is therefore a bad bet. Additions and removals are the reliable events.
The handler fires for the folder it is attached to, not for that folder's descendants. A nested tree needs each folder attached separately, which is the point at which most people go looking for a different tool.
Where the pieces live on disk
Three locations matter, and on a current macOS release they are not all where the archived documentation puts them.
Scripts are looked for in /Library/Scripts/Folder Action Scripts and ~/Library/Scripts/Folder Action Scripts. The system folder ships with working samples, and reading them is the fastest way to learn the syntax. The set installed includes add - new item alert.scpt, close - close sub-folders.scpt, open - show comments in dialog.scpt, convert - PostScript to PDF.scpt, and nine image scripts covering rotation, flipping, icon addition, and duplication as JPEG, PNG or TIFF.
The configuration app is Folder Actions Setup.app. Apple's archived reference gives its path as /System/Library/CoreServices, and an older page in the same document says /Applications/AppleScript. On macOS 27 it is at /System/Library/CoreServices/Applications/Folder Actions Setup.app. Searching for it by name in Spotlight is more durable than memorising a path that has moved twice.
The component that watches folders and calls the handlers is FolderActionsDispatcher.app, in /System/Library/CoreServices. It is not something to launch by hand, but knowing it exists explains what has to be running for any of this to work.
Folder Actions Setup does more than attach a script. It enables or disables Folder Actions globally, lists the folders that currently have scripts, attaches more than one script to a single folder, and enables or disables each attachment individually. That last control is the one to reach for when a folder starts misbehaving, because disabling one script is far easier to reason about than editing it while it is live.
The empty hot folder rule
Apple states the rule in a single sentence that is easy to skim past: a well written Folder Action script leaves the hot folder empty. This avoids repeated application of the action to the same files, and lets Folder Actions perform more efficiently.
That is not a style preference. It is the difference between a folder that files things and a folder that files the same thing forty times.
Consider a script attached to Downloads that renames each arriving PDF and leaves it in place. The rename is a change to the folder contents. Depending on how the rename is performed, the renamed file can register as a new arrival, which calls the handler again. Apple's own sample for adding folder items to shows the discipline that avoids this: it creates a Done subfolder, writes its output there, and explicitly skips items whose extension is already zip or sit so that its own output is never reprocessed.
The two habits that come out of this are worth adopting before writing a single line. Move the result out of the watched folder. And make the handler skip anything that looks like its own output, by extension, by prefix, or by location.
The removal handler is weaker than it looks
on removing folder items from is the handler people reach for when they want a log of what left a folder, and it disappoints for a structural reason. It receives an alias to the folder, and an alias identifies something that exists. By the time the handler runs, the item has already gone somewhere else, or into the Trash, so anything the script wants to say about it has to be reconstructed rather than read.
The workable pattern is to keep the state elsewhere. A script attached with the additions handler can append each arriving filename to a plain text list, and a separate check can compare that list against the folder's current contents. That is more moving parts than most people want, which is a fair signal that auditing a folder is a job for a tool built to keep history rather than for an event handler.
Multiple scripts can be attached to one folder, and Folder Actions Setup enables or disables each one separately. What the documentation does not define is the order in which two scripts attached to the same folder and listening for the same event will run. Any pair where the second depends on what the first did should be one script, not two.
Reading the shipped samples first is worth the ten minutes. add - new item alert.scpt shows the minimum viable additions handler. close - close sub-folders.scpt shows the window handler in a form that actually works. The nine image scripts show the loop over these_items with a guard against reprocessing, which is the shape most custom rules end up needing.
Four ways to watch a folder
Folder Actions is one option among four, and they fail in different places.
| Mechanism | Written in | Cost | Recurses into subfolders | Notes |
|---|---|---|---|---|
| Folder Actions | AppleScript | Included | No | Five documented events, per-folder attachment |
| Automator Folder Action workflow | Automator actions | Included | No | Same trigger, visual editor instead of script |
launchd WatchPaths |
Any executable | Included | No | Apple's man page discourages it, see below |
| Hazel | Rule editor | $42, family pack $65 | Yes, by rule | Third-party, rules with pattern matching |
The launchd row deserves the quote in full, because it is unusually blunt for a manual page. man launchd.plist says of WatchPaths that use of the key is highly discouraged, as filesystem event monitoring is highly race-prone, and it is entirely possible for modifications to be missed. It adds that when modifications are caught, there is no guarantee that the file will be in a consistent state when the job is launched.
That second sentence is the trap that catches Folder Actions users too. A large download is an item in the folder well before it is a complete file. Any handler that opens, hashes, or converts an arriving item needs to cope with an item that is still growing, either by skipping partial-download extensions or by waiting until the size stops changing before touching it.
The same manual page offers QueueDirectories, which keeps a job alive as long as the named directory is not empty. That is a different and often better model: the job drains a queue folder rather than reacting to each event, and a missed event simply means the item waits for the next run.
Hazel is the commercial answer, priced at $42 for a single licence, $65 for a household pack of up to five, and $20 to upgrade from a previous version. It replaces script writing with a rule editor and handles the recursion and the pattern matching that Folder Actions leaves to the author.
Getting real work out of the handler
AppleScript is a poor language for the logic most of these rules need, and there is no obligation to write the logic in it. The handler can be a thin dispatcher.
Inside a handler, do shell script hands a POSIX path to a shell command. Apple's own ZIP sample does exactly this, calling /usr/bin/ditto with quoted POSIX paths rather than trying to archive files in AppleScript. The pattern generalises: loop over the received aliases, convert each to a quoted POSIX path, and pass it to a script written in whatever language the rest of the work is in.
The Shortcuts app can be the destination as well. man shortcuts documents shortcuts run shortcut-name-or-identifier, with --input-path for the input and --output-path for the result. A folder action that calls shortcuts run on each arriving file moves all of the branching into a visual editor while keeping the folder trigger.
Once the handler is a one-line dispatcher, the real work is an ordinary script that can be run by hand on a test file. That is the point of the arrangement: a rule that can only be tested by dropping a file into a live folder is a rule nobody will dare to change. Running the same script from a prompt in the folder being watched, with the output visible, is how it gets debugged, and keeping folders and a terminal in one window removes the window juggling that makes that loop tedious.
What breaks, and how to tell
Four failure modes account for nearly all reports.
Nothing happens at all. Folder Actions has a global on switch and a per-attachment on switch, and both are in Folder Actions Setup. Check the global one first.
It happens repeatedly on the same file. The handler is reprocessing its own output. Apply the empty hot folder rule.
It happens on incomplete files. Add a guard on partial extensions, or move to a queue-draining design.
It fails silently on protected folders. Scripted access to the Desktop, Documents and Downloads folders is gated by macOS privacy controls, so a handler that works on a folder in a scratch directory and fails in Downloads is a permissions result, not a syntax error.
What to change first
Attach one script to one folder that is not Downloads, and have it move files out rather than rename them in place. Once that has run cleanly for a week, decide whether the remaining rules are worth writing in AppleScript or worth $42 of rule editor, and read the answers to the common setup questions before adding the second attachment. If the filing decisions keep needing a look at the file first, the missing piece is a window where the folder, the command line and a preview sit together, which is what Atriens is built to do.
Frequently asked questions
Why does my folder action run twice on the same file?
Almost always because the handler modifies the file in place, and that modification counts as a change to the folder. Apple's guidance is that a well written script leaves the hot folder empty, and its own sample writes output to a Done subfolder while skipping files whose extension matches its own output. Move the result out, and filter out anything the script itself produced.
Can a folder action watch subfolders too?
Not on its own. The handler is invoked for the folder the script is attached to, so each subfolder needs its own attachment. Recursion across a tree is the case where a rule-based tool such as Hazel, or a queue-draining launchd job, is the better fit.
Where is Folder Actions Setup on a current macOS?
On macOS 27 it is at /System/Library/CoreServices/Applications/Folder Actions Setup.app. Apple's archived reference lists two older paths, so searching for the app by name is more reliable than the documented location. Control-clicking a folder in the Finder also exposes Folder Action controls.
Should launchd be used instead of a folder action?
Only with the caveat Apple attaches to it. The launchd.plist manual page calls WatchPaths highly discouraged and race-prone, and warns that a file may not be in a consistent state when the job starts. The QueueDirectories key in the same page is the sturdier pattern, because a missed event only delays the work rather than losing it.
Can a folder action run a Shortcut or a shell script?
Yes, and that is usually the better structure. do shell script inside the handler passes a POSIX path to any command, which is what Apple's own archiving sample does with ditto. For Shortcuts, man shortcuts documents shortcuts run with --input-path, so the handler can stay a single line and all the logic can live where it is easier to edit.