package fileutils import ( "errors" "os" "path/filepath" ) // CopyDir copies a directory from source to dest and all // of its sub-directories. It doesn't stop if it finds an error // during the copy. Returns an error if any. func CopyDir(source, dest string) error { // Get properties of source. srcinfo, err := os.Stat(source) if err != nil { return err } // Create the destination directory. err = os.MkdirAll(dest, srcinfo.Mode()) if err != nil { return err } dir, err := os.Open(source) if err != nil { return err } defer dir.Close() obs, err := dir.Readdir(-1) if err != nil { return err } var errs []error for _, obj := range obs { fsource := filepath.Join(source, obj.Name()) fdest := filepath.Join(dest, obj.Name()) if obj.IsDir() { // Create sub-directories, recursively. err = CopyDir(fsource, fdest) if err != nil { errs = append(errs, err) } } else { // Perform the file copy. err = CopyFile(fsource, fdest) if err != nil { errs = append(errs, err) } } } var errString string for _, err := range errs { errString += err.Error() + "\n" } if errString != "" { return errors.New(errString) } return nil }