Browse the docs

File or folder change

Runs the macro when a file or folder in a watched place is added, changed, removed, renamed, moved or tagged, with patterns, depth, settling, batching and catch-up.

A file changes in path

Keyboard Maestro: Folder

Details #

Switchboard watches path with the system's file event stream. The path may be a folder or a single file, ~ is expanded and symlinks are resolved. A folder that doesn't exist yet is watched through its nearest existing parent and the trigger arms when it appears. A volume that is unmounted disarms the trigger and re-arms it when it comes back.

Events. events lists what to react to: created, modified, deleted, renamed (same folder, new name), moved (into or out of a different folder), tagged (a Finder tag was added; name it with tag) or any. The older single event still works, and events wins when both are present. An atomic save (an editor writing a temp file and renaming it over the original) is one modified, not a delete and a create. Moving a file out of the watched tree is deleted, moving one in is created; both carry movedFrom or movedTo when known.

Filters. All optional, all applied in this order:

  • depth: how deep below path. 0 is the folder's own items, 1 adds one level of subfolders, "all" (the default) is every level.

  • match and exclude: lists of globs on the file name: *.pdf, Invoice *, *.{jpg,png,heic}. Case does not matter. exclude adds to the built-in list below, and match narrows what is left.

  • name: an exact file name, or a name without its extension (kept for Keyboard Maestro's Trigger File).

  • kind: files (default), folders or both.

  • conformsTo: type identifiers such as public.image or com.adobe.pdf.

  • tag: with tagged, the Finder tag that must have been added.

Always excluded. .DS_Store, ._*, .localized, Icon\r, *.download, *.crdownload, *.part, *.partial, *.tmp, ~$*, .~lock.*, *.sb-*, .#*, *.swp, anything inside a .git folder and anything inside a package (.app, .photoslibrary, .bundle and the like), unless path is that package.

Settle. A matching created or modified waits until the file's size and modification date have stayed the same for settle seconds (default 2, checked every half second), then fires once. A half-copied file or a download in progress therefore fires when it is whole, under its final name. A file deleted while it settles fires nothing. An iCloud file that is still downloading waits for the download, up to ten minutes. settle: 0 fires at once. Deleted, renamed, moved and tagged events never wait.

Batch. With batch, matching events are collected and the macro runs once, batch seconds after the last one, with the whole list in files. Without it each file runs the macro on its own, and the macro's overlap setting decides whether they queue. Either way one trigger is capped at 500 events a minute; past that it pauses for the rest of the minute and says so in Activity.

Your own changes. A macro does not fire for a path its own run wrote, moved or deleted with its file steps, until a few seconds after the run ends. A macro that renames Invoice.pdf to 2026-10 Invoice.pdf in the folder it watches therefore runs once. Other macros still see the change.

Catch-up. With catchUp, when the engine starts it replays what happened in the folder while it was off (from the last event it saw, or by looking at file dates when the history is gone). Without it, starting means "from now".

Network volumes. SMB, AFP, NFS and FUSE volumes don't report changes reliably, so they are polled every 10 seconds by default; poll sets the seconds, and works on any folder.

Permissions. Desktop, Documents, Downloads, iCloud Drive, removable and network volumes are protected by macOS. When Switchboard can't read the folder the When row says so and opens the right Privacy pane.

Inputs. The run gets a file input: {path, name, stem, ext, folder, event, size, uti, tags, isDirectory} plus oldName, movedFrom, movedTo and tag when they apply. With batch it also gets files, a list of those. {{triggerValue}} is the full path (the paths joined by newlines for a batch), not the folder you watch.

Secure input does not affect this trigger.

Parameters #

ParameterTypeRequiredValuesWhat it does
pathtextYesA folder or file to watch. Use ~ for your home folder.
batchnumberSeconds to collect events into one run.
catchUpyes / noRun for what happened while the engine was off.
conformsTolist of textType identifiers the file must conform to.
depthany value0, a number of levels, or "all".
eventone ofcreated modified deleted renamed moved tagged anyOne event. Used when events is absent. Defaults to created.
eventslist ofcreated modified deleted renamed moved tagged anyA list of created, modified, deleted, renamed, moved, tagged or any.
excludelist of textGlobs that rule a file out.
kindone offiles folders bothfiles, folders or both.
matchlist of textGlobs the file name must match one of.
nametextOnly fire for a file with this name (the match ignores case and the extension).
pollnumberSeconds between looks, for folders the system can't watch.
settlenumberSeconds a new or changed file must stay unchanged. Default 2.
tagtextThe Finder tag, for tagged.

Every trigger also takes Limits: a cooldown, the first time each day, every nth time, twice within seconds, a chance, only while you are at the Mac, on one Mac, or in a State. See Limits on any trigger.

Examples #

Announce a new download
When
  1. A file is created in ~/Downloads
Do
  1. Show “New file: {{triggerValue}}”
Open in Switchboard to try it
Tell me about each new PDF in Downloads (top level only, once it is whole)
When
  1. A file is created in ~/Downloads matching “*.pdf”
Do
  1. Show “PDF: {{triggerValue}}”
Open in Switchboard to try it

Gotchas #

  • Folders Switchboard cannot read (without the right privacy permission) give no events; the When row shows why.

  • A file you copy in is "created" only once it has stopped growing, so a 2 GB copy fires after it finishes, not when it starts.

  • Under the When row the editor lists the last events that matched and the last that were filtered out, each with the reason, so you can see why a file did or didn't fire.

  • Not fired reasons: disabled, groupOff, scope, paused, conditionFalse, ownChange, stillDownloading, storm, noAccess.

See also #

Device attach or detach, Triggers