README.md
1# watcher
2
3[![Build Status](https://travis-ci.org/radovskyb/watcher.svg?branch=master)](https://travis-ci.org/radovskyb/watcher)
4
5`watcher` is a Go package for watching for files or directory changes (recursively or non recursively) without using filesystem events, which allows it to work cross platform consistently.
6
7`watcher` watches for changes and notifies over channels either anytime an event or an error has occurred.
8
9Events contain the `os.FileInfo` of the file or directory that the event is based on and the type of event and file or directory path.
10
11[Installation](#installation)
12[Features](#features)
13[Example](#example)
14[Contributing](#contributing)
15[Watcher Command](#command)
16
17# Update
18- Added new file filter hooks (Including a built in regexp filtering hook) [Dec 12, 2018]
19- Event.Path for Rename and Move events is now returned in the format of `fromPath -> toPath`
20
21#### Chmod event is not supported under windows.
22
23# Installation
24
25```shell
26go get -u github.com/radovskyb/watcher/...
27```
28
29# Features
30
31- Customizable polling interval.
32- Filter Events.
33- Watch folders recursively or non-recursively.
34- Choose to ignore hidden files.
35- Choose to ignore specified files and folders.
36- Notifies the `os.FileInfo` of the file that the event is based on. e.g `Name`, `ModTime`, `IsDir`, etc.
37- Notifies the full path of the file that the event is based on or the old and new paths if the event was a `Rename` or `Move` event.
38- Limit amount of events that can be received per watching cycle.
39- List the files being watched.
40- Trigger custom events.
41
42# Todo
43
44- Write more tests.
45- Write benchmarks.
46
47# Example
48
49```go
50package main
51
52import (
53 "fmt"
54 "log"
55 "time"
56
57 "github.com/radovskyb/watcher"
58)
59
60func main() {
61 w := watcher.New()
62
63 // SetMaxEvents to 1 to allow at most 1 event's to be received
64 // on the Event channel per watching cycle.
65 //
66 // If SetMaxEvents is not set, the default is to send all events.
67 w.SetMaxEvents(1)
68
69 // Only notify rename and move events.
70 w.FilterOps(watcher.Rename, watcher.Move)
71
72 // Only files that match the regular expression during file listings
73 // will be watched.
74 r := regexp.MustCompile("^abc$")
75 w.AddFilterHook(watcher.RegexFilterHook(r, false))
76
77 go func() {
78 for {
79 select {
80 case event := <-w.Event:
81 fmt.Println(event) // Print the event's info.
82 case err := <-w.Error:
83 log.Fatalln(err)
84 case <-w.Closed:
85 return
86 }
87 }
88 }()
89
90 // Watch this folder for changes.
91 if err := w.Add("."); err != nil {
92 log.Fatalln(err)
93 }
94
95 // Watch test_folder recursively for changes.
96 if err := w.AddRecursive("../test_folder"); err != nil {
97 log.Fatalln(err)
98 }
99
100 // Print a list of all of the files and folders currently
101 // being watched and their paths.
102 for path, f := range w.WatchedFiles() {
103 fmt.Printf("%s: %s\n", path, f.Name())
104 }
105
106 fmt.Println()
107
108 // Trigger 2 events after watcher started.
109 go func() {
110 w.Wait()
111 w.TriggerEvent(watcher.Create, nil)
112 w.TriggerEvent(watcher.Remove, nil)
113 }()
114
115 // Start the watching process - it'll check for changes every 100ms.
116 if err := w.Start(time.Millisecond * 100); err != nil {
117 log.Fatalln(err)
118 }
119}
120```
121
122# Contributing
123If you would ike to contribute, simply submit a pull request.
124
125# Command
126
127`watcher` comes with a simple command which is installed when using the `go get` command from above.
128
129# Usage
130
131```
132Usage of watcher:
133 -cmd string
134 command to run when an event occurs
135 -dotfiles
136 watch dot files (default true)
137 -ignore string
138 comma separated list of paths to ignore
139 -interval string
140 watcher poll interval (default "100ms")
141 -keepalive
142 keep alive when a cmd returns code != 0
143 -list
144 list watched files on start
145 -pipe
146 pipe event's info to command's stdin
147 -recursive
148 watch folders recursively (default true)
149 -startcmd
150 run the command when watcher starts
151```
152
153All of the flags are optional and watcher can also be called by itself:
154```shell
155watcher
156```
157(watches the current directory recursively for changes and notifies any events that occur.)
158
159A more elaborate example using the `watcher` command:
160```shell
161watcher -dotfiles=false -recursive=false -cmd="./myscript" main.go ../
162```
163In this example, `watcher` will ignore dot files and folders and won't watch any of the specified folders recursively. It will also run the script `./myscript` anytime an event occurs while watching `main.go` or any files or folders in the previous directory (`../`).
164
165Using the `pipe` and `cmd` flags together will send the event's info to the command's stdin when changes are detected.
166
167First create a file called `script.py` with the following contents:
168```python
169import sys
170
171for line in sys.stdin:
172 print (line + " - python")
173```
174
175Next, start watcher with the `pipe` and `cmd` flags enabled:
176```shell
177watcher -cmd="python script.py" -pipe=true
178```
179
180Now when changes are detected, the event's info will be output from the running python script.
181