A .path unit watches the filesystem (via inotify) and starts a paired .service when the watched path changes. Great for “process a file when it lands in this drop folder” without a polling loop.
1. The service (the work)
/etc/systemd/system/ingest.service:
[Unit]
Description=Ingest dropped files
[Service]
Type=oneshot
ExecStart=/usr/local/bin/ingest.sh
A Type=oneshot service, no [Install] — the path unit starts it.
2. The path (the watcher)
/etc/systemd/system/ingest.path (same base name → triggers ingest.service):
[Unit]
Description=Watch the drop folder
[Path]
PathExistsGlob=/srv/incoming/*.csv
# or: PathChanged=/etc/myapp/config.yaml
# or: PathModified=/var/log/app/app.log
[Install]
WantedBy=multi-user.target
The watch conditions:
PathExists=— fires while the path exists (and re-fires when it’s recreated).PathExistsGlob=— same, with a glob (e.g. any*.csvin a folder).PathChanged=— fires when the file/dir is closed after writing (one event per write session — usually what you want).PathModified=— fires on every write, not just on close (chattier).DirectoryNotEmpty=— fires whenever the directory is non-empty.
Enable the path watcher
sudo systemctl daemon-reload
sudo systemctl enable --now ingest.path
# Test:
touch /srv/incoming/test.csv
journalctl -u ingest.service -f
Gotchas: enable the .path, not the .service. To trigger a different service, add Unit=other.service under [Path]. Have your script move or delete the file it handled — otherwise PathExists* conditions stay true and the service won’t re-trigger for the next file with the same name. For high-volume drop folders, PathChanged= avoids the duplicate events PathModified= produces mid-write.