Skip to content

Add FileWatcher spoon for automatic file organization - #347

Open
danielo515 wants to merge 2 commits into
Hammerspoon:masterfrom
danielo515:add-filewatcher-spoon
Open

Add FileWatcher spoon for automatic file organization#347
danielo515 wants to merge 2 commits into
Hammerspoon:masterfrom
danielo515:add-filewatcher-spoon

Conversation

@danielo515

Copy link
Copy Markdown

FileWatcher Spoon

This PR adds a new spoon for automatic file organization based on pattern matching rules.

Features

  • Automatic file organization with Lua pattern matching (case-insensitive)
  • Desktop notifications when files are moved
  • Automatic conflict resolution - appends numbers to duplicate filenames
  • Tilde expansion support for paths (~ for home directory)
  • Chainable API - all methods return the spoon object

Use Cases

  • Organize downloads automatically (PDFs to Documents, images to Pictures, etc.)
  • Sort screenshots from Desktop to a dedicated folder
  • Project file organization by type
  • Any scenario requiring automatic file sorting based on patterns

Example Usage

hs.loadSpoon("FileWatcher")

-- Watch Downloads folder and organize files
spoon.FileWatcher:watchDirectory("~/Downloads", {
  { pattern = "%.pdf$", destination = "~/Documents/PDFs" },
  { pattern = "%.jpg$", destination = "~/Pictures" },
  { pattern = "%.png$", destination = "~/Pictures" },
  { pattern = "%.zip$", destination = "~/Downloads/Archives" }
})

API Documentation

  • Full API documentation included in docs.json (generated using hs -c "hs.doc.builder.genJSON(...)")
  • Follows Hammerspoon Spoon conventions
  • Includes :init(), :start(), :stop(), :watchDirectory(), :stopWatching(), and :stopAllWatchers() methods

Testing

Tested on macOS with various file types and patterns. Files are moved correctly with proper conflict resolution and notifications.

@muescha

muescha commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

I would do it in a more generic way:

  • Matchers:
    • PatternMatcher: checks whether a filename matches a regex
    • DateMatcher: checks for some date
  • Actions:
    • FileMover
    • FileRenamer
    • ...

This makes it more extensible and open to additional options in the future:

spoon.FileWatcher:watchDirectory("~/Downloads", {
  { 
  	PatternMatcher("%.pdf$"), 
  	ActionRenameAs("{currentDate}-*"), 
  	ActionMoveTo("~/Documents/PDFs") 
  	},
  { 
  	PatternMatcher("%.png$"), 
  	ActionMoveTo("~/Pictures") 
  },
})

@danielo515

Copy link
Copy Markdown
Author

That is indeed more flexible, but it is also (probably) harder to understand for simple users that have simple use cases.
Where are those Matchers and Actions coming from?

And, even if we agree, there isn't much interest into merging this spoon anyway. It has been sitting here for an entire year and yours is the first comment about it, so I'm not willing to put any more effort for an potential outcome of being ignored

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants