Skip to content

Instantly share code, notes, and snippets.

@vzctl
Created March 1, 2013 17:25
Show Gist options
  • Save vzctl/5066253 to your computer and use it in GitHub Desktop.
Save vzctl/5066253 to your computer and use it in GitHub Desktop.
package main
import (
"flag"
"log"
"os"
"path"
)
var src = flag.String("src", "/usr", "source path")
var dst = flag.String("dst", "/usr.copy", "destination path")
func copyEntries(src string, dst string) error {
f, err := os.Open(src)
if err != nil {
return err
}
infos, err := f.Readdir(-1)
f.Close()
if err != nil {
return err
}
dircount := 0
errs := make(chan error, len(infos))
for _, fi := range infos {
csrc := path.Join(src, fi.Name())
cdst := path.Join(dst, fi.Name())
if fi.IsDir() {
go func(fi os.FileInfo) {
errs <- copy(csrc, cdst, fi)
}(fi)
dircount += 1
} else {
copy(csrc, cdst, fi)
}
}
for i := 0; i < dircount; i++ {
if err := <-errs; err != nil {
return err
}
}
return nil
}
func copy(src string, dst string, fi os.FileInfo) error {
mod := fi.Mode()
switch {
case mod&os.ModeSymlink != 0:
if tgt, err := os.Readlink(src); err != nil {
return err
} else {
if err := os.Symlink(tgt, dst); err != nil {
return err
}
}
case mod&os.ModeDir != 0:
if err := os.Mkdir(dst, mod); err != nil {
return err
}
if err := copyEntries(src, dst); err != nil {
return err
}
default:
if err := os.Link(src, dst); err != nil {
return err
}
}
return nil
}
func main() {
flag.Parse()
if err := os.Mkdir(*dst, 0755); err != nil && !os.IsExist(err) {
log.Fatal(err)
}
if err := copyEntries(*src, *dst); err != nil {
log.Fatal(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment