Skip to content

Instantly share code, notes, and snippets.

@nimezhu
Created September 21, 2017 19:34
Show Gist options
  • Save nimezhu/37ffa0de41009b0d6c46d189676f8388 to your computer and use it in GitHub Desktop.
Save nimezhu/37ffa0de41009b0d6c46d189676f8388 to your computer and use it in GitHub Desktop.
package fs
//watch a directory rursively.
import (
"fmt"
"log"
"os"
"path/filepath"
observable "github.com/GianlucaGuarini/go-observable"
"github.com/howeyc/fsnotify"
)
type Fs struct {
W map[string]*fsnotify.Watcher
Root string
Dir *File
o *observable.Observable
}
func NewFs(root string) *Fs {
fs := &Fs{
make(map[string]*fsnotify.Watcher),
root,
Open(root),
observable.New(),
}
fs.open(root)
return fs
}
func (fs *Fs) visit(path string, f os.FileInfo, err error) error {
fmt.Printf("Visited: %s\n", path)
fmt.Printf("File %s\n", f.IsDir())
if f.IsDir() {
fs.W[path], _ = fsnotify.NewWatcher()
fs.W[path].Watch(path)
go func() {
for {
select {
case ev := <-fs.W[path].Event:
log.Println("event:", path, ev)
case err := <-fs.W[path].Error:
log.Println("error:", path, err)
}
}
}()
}
return nil
}
func (fs *Fs) open(root string) error {
err := filepath.Walk(root, fs.visit)
return err
}
func (fs *Fs) Json() string {
return fs.Dir.Json()
}
package fs
import (
"fmt"
"testing"
)
func TestWalk(t *testing.T) {
rootFile := Open("/home/zhuxp/Pictures")
//output, _ := json.MarshalIndent(rootFile, "", " ")
fmt.Println(rootFile.Json())
/*
log.Println("Listening...")
log.Println("Please open http://127.0.0.1:8080")
log.Fatal(http.ListenAndServe(":8080", nil))
*/
}
package fs
import (
"encoding/json"
"io/ioutil"
"os"
"path/filepath"
"time"
)
type File struct {
ModifiedTime time.Time `json:"modifiedTime"`
IsLink bool `json:"isLink"`
IsDir bool `json:"isDir"`
LinksTo string `json:"linksTo"`
Size int64 `json:"size"`
Name string `json:"name"`
Path string `json:"path"`
Children []*File `json:"children"`
}
func (f *File) Json() string {
output, _ := json.MarshalIndent(f, "", " ")
return string(output)
}
func Open(path string) *File {
rootOSFile, _ := os.Stat(path)
rootFile := toFile(rootOSFile, path) //start with root file
stack := []*File{rootFile}
for len(stack) > 0 { //until stack is empty,
file := stack[len(stack)-1] //pop entry from stack
stack = stack[:len(stack)-1]
children, _ := ioutil.ReadDir(file.Path) //get the children of entry
for _, chld := range children { //for each child
child := toFile(chld, filepath.Join(file.Path, chld.Name())) //turn it into a File object
file.Children = append(file.Children, child) //append it to the children of the current file popped
stack = append(stack, child) //append the child to the stack, so the same process can be run again
}
}
return rootFile
}
func toFile(file os.FileInfo, path string) *File {
JSONFile := File{ModifiedTime: file.ModTime(),
IsDir: file.IsDir(),
Size: file.Size(),
Name: file.Name(),
Path: path,
Children: []*File{},
}
if file.Mode()&os.ModeSymlink == os.ModeSymlink {
JSONFile.IsLink = true
JSONFile.LinksTo, _ = filepath.EvalSymlinks(filepath.Join(path, file.Name()))
} // Else case is the zero values of the fields
return &JSONFile
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment