在围棋里有复制目录的简单方法吗? 我有以下功能:

err = CopyDir("sourceFolder","destinationFolder")

到目前为止,包括github.com/cf-guardian/guardian/kernel/fileutils等库在内的任何东西都没有正常工作

需要注意的一点是,我需要复制preserve directory structure个文件夹,包括sourceFolder本身,而不是简单地复制文件夹的所有内容.

推荐答案

我认为docker实现可以被认为是处理边缘情况的完整解决方案: https://github.com/moby/moby/blob/master/daemon/graphdriver/copy/copy.go

有以下几点好处:

  • 不支持的文件类型上升错误
  • 保留权限和所有权
  • 保留扩展属性
  • 保留时间戳

但是由于大量的导入,您的小应用程序变得很大.

我try 了多种解决方案,但只使用stdlib和Linux:

func CopyDirectory(scrDir, dest string) error {
    entries, err := ioutil.ReadDir(scrDir)
    if err != nil {
        return err
    }
    for _, entry := range entries {
        sourcePath := filepath.Join(scrDir, entry.Name())
        destPath := filepath.Join(dest, entry.Name())

        fileInfo, err := os.Stat(sourcePath)
        if err != nil {
            return err
        }

        stat, ok := fileInfo.Sys().(*syscall.Stat_t)
        if !ok {
            return fmt.Errorf("failed to get raw syscall.Stat_t data for '%s'", sourcePath)
        }

        switch fileInfo.Mode() & os.ModeType{
        case os.ModeDir:
            if err := CreateIfNotExists(destPath, 0755); err != nil {
                return err
            }
            if err := CopyDirectory(sourcePath, destPath); err != nil {
                return err
            }
        case os.ModeSymlink:
            if err := CopySymLink(sourcePath, destPath); err != nil {
                return err
            }
        default:
            if err := Copy(sourcePath, destPath); err != nil {
                return err
            }
        }

        if err := os.Lchown(destPath, int(stat.Uid), int(stat.Gid)); err != nil {
            return err
        }

        isSymlink := entry.Mode()&os.ModeSymlink != 0
        if !isSymlink {
            if err := os.Chmod(destPath, entry.Mode()); err != nil {
                return err
            }
        }
    }
    return nil
}

func Copy(srcFile, dstFile string) error {
    out, err := os.Create(dstFile)
    if err != nil {
        return err
    }

    defer out.Close()

    in, err := os.Open(srcFile)
    defer in.Close()
    if err != nil {
        return err
    }

    _, err = io.Copy(out, in)
    if err != nil {
        return err
    }

    return nil
}

func Exists(filePath string) bool {
    if _, err := os.Stat(filePath); os.IsNotExist(err) {
        return false
    }

    return true
}

func CreateIfNotExists(dir string, perm os.FileMode) error {
    if Exists(dir) {
        return nil
    }

    if err := os.MkdirAll(dir, perm); err != nil {
        return fmt.Errorf("failed to create directory: '%s', error: '%s'", dir, err.Error())
    }

    return nil
}

func CopySymLink(source, dest string) error {
    link, err := os.Readlink(source)
    if err != nil {
        return err
    }
    return os.Symlink(link, dest)
}

Go相关问答推荐

CGO如何转换为文件*类型

Go在使用HTTP代理时如何处理DNS请求?

map 中的多个函数类型,Golang

即使HTTP服务器正在使用GO和Protobuf、SQL Server启动,请求也不返回结果

使用!NOT运算符的Golang文本/模板多个条件

如何在链接中写入链接

无法使用exec从管道中读取.Go中的命令

从文件读取字节,将其保存到 struct 体并修改值

当我有外键时,如何使用 GORM 创建数据库的新条目

Golang:访问any类型泛型上的字段

Go Template 动态获取变量

如何将字节文件高效地读入int64切片?

尽管存在 WaitGroup,Goroutines 似乎被打断了

加载 docker 镜像失败

如何在 Golang http.Request 对象中读取自定义 ajaxParams

使用 os/exec 和在命令行执行之间的结果莫名其妙地不同

在 Go GRPC 服务器流式拦截器上修改元数据

如何编写一个以字符串或错误为参数的通用函数?

函数超时和 goroutine 泄漏

在 Go 中将指针传递给函数的正确方法是什么,以便我可以读取和/或修改指针表示的值?