commit 8cece4b4899a1e38f5cb22b18d5dbdae78e0e369 Author: Avril Date: Mon Jun 1 19:47:39 2020 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..08efc1c --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +test/ +test.txt +*~ +glue diff --git a/README b/README new file mode 100644 index 0000000..3915620 --- /dev/null +++ b/README @@ -0,0 +1,5 @@ +Hardlink files to a subdir path + +e.g: + +$ find | grep -iE '\.(jpg|png|gif)$' | glue ./image-backup diff --git a/main.go b/main.go new file mode 100644 index 0000000..16e8260 --- /dev/null +++ b/main.go @@ -0,0 +1,83 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "path" + "sync" +) + +func oneechan(output chan string) { + reader := bufio.NewReader(os.Stdin) + for { + if text, err := reader.ReadString('\n'); err != nil { + fmt.Println("[e] Reading from stdin failed, closing: ", err) + break; + } else { + output <- text[:len(text)-1] + } + } + close(output) +} + +var shadow bool = false + +func worker(from, to string, wg *sync.WaitGroup) { + defer wg.Done() + + if _, err := os.Stat(from); os.IsNotExist(err) { + fmt.Println("[w] input file does not exist: ",from) + return + } else { + fmt.Printf("[i] %v -> %v\n", from, to) + } + + if !shadow { + parent_dir, _ := path.Split(to) + + if _, err := os.Stat(parent_dir); os.IsNotExist(err) { + if err := os.MkdirAll(parent_dir, os.ModePerm); err != nil { + fmt.Printf("[e] failed to create structure `%s`: %v\n", parent_dir, err) + return + } + } + + if err := os.Link(from, to); err != nil { + fmt.Printf("[e] failed to create hardlink `%s`: %v\n", to, err) + } + } + +} + +func imouto(root string, input chan string) { + var wg sync.WaitGroup + for from := range input { + to := path.Join(root, from) + + wg.Add(1) + go worker(from, to, &wg) + } + wg.Wait() +} + +func main() { + + if len(os.Args) < 2 { + fmt.Println("usage: glue [--shadow] ") + fmt.Println(" -shadow: do not link files or build directory structure") + return + } + + i := 1 + if os.Args[1] == "--shadow" { + shadow = true + i+=1 + } + + paths := make(chan string) + root := os.Args[i] + + go oneechan(paths) + imouto(root, paths) +}