golang拷贝目录(持续更新中)

川长思鸟来 2022-12-02 01:27 417阅读 0赞

思路

首先遍历源目录,将所有的目录和文件分别存储在两个切片中,然后先创建所有的目录,然后在创建所有的文件。

目前不会处理连接文件

上代码

  1. package models
  2. import (
  3. "bufio"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "os"
  8. "path/filepath"
  9. "strings"
  10. )
  11. //WalkFile 文件对象
  12. type WalkFile struct{
  13. Fname string
  14. Fmode os.FileMode
  15. }
  16. //Dir 目录对象
  17. type Dir struct {
  18. //父目录
  19. ParentName string
  20. //目录的名字
  21. DirName string
  22. //目录下所有的目录
  23. DirList []WalkFile
  24. //目录下所有文件
  25. FileList []WalkFile
  26. //文件已经存在时 是否删除
  27. FileDelSign bool
  28. }
  29. //visit 浏览文件 区分为目录和文件
  30. func(my *Dir) visit(path string, f os.FileInfo, err error) error {
  31. tmpPath := strings.Replace(path, my.ParentName, "",1)
  32. if f == nil {
  33. return err
  34. }
  35. if f.IsDir(){
  36. my.DirList = append(my.DirList, WalkFile{ Fname: tmpPath, Fmode: f.Mode()})
  37. }else if (f.Mode() & os.ModeSymlink) > 0 {
  38. linkError := "!!! ERROR Do not support symbol link"
  39. fmt.Println(linkError)
  40. return errors.New(linkError)
  41. }else{
  42. my.FileList= append(my.FileList, WalkFile{ Fname: tmpPath, Fmode: f.Mode()})
  43. }
  44. return nil
  45. }
  46. //CreateDir 创建目录
  47. func (my *Dir) CreateDir(dest string, mode os.FileMode) error{
  48. //如果目录存在就直接返回
  49. if _,err:=os.Stat(dest); err!=nil{
  50. mkErr := os.MkdirAll(dest, mode)
  51. if mkErr != nil{
  52. return mkErr
  53. }
  54. }
  55. return nil
  56. }
  57. //CreateFile 创建文件
  58. func (my *Dir) CreateFile(sr string, dest string, mode os.FileMode) error{
  59. //判断文件是否存在,如果存在根据FileDelSign决定是否删除
  60. if _,err:=os.Stat(dest); err==nil{
  61. if my.FileDelSign{
  62. if rError := os.Remove(dest); rError != nil {
  63. return rError
  64. }
  65. } else {
  66. return nil
  67. }
  68. }
  69. //拷贝文件
  70. srcFile, err := os.Open(sr)
  71. if err != nil {
  72. return err
  73. }
  74. defer func() {
  75. err := srcFile.Close()
  76. if err!=nil{
  77. fmt.Printf("close file failed %v\n", err)
  78. }
  79. }()
  80. //通过srcFile,获取到READER
  81. reader := bufio.NewReader(srcFile)
  82. //打开dstFileName
  83. dstFile, err := os.OpenFile(dest, os.O_WRONLY|os.O_CREATE, mode)
  84. if err != nil {
  85. return err
  86. }
  87. //通过dstFile,获取到WRITER
  88. writer := bufio.NewWriter(dstFile)
  89. //writer.Flush()
  90. defer func() {
  91. err := dstFile.Close()
  92. if err!=nil{
  93. fmt.Printf("close file failed %v\n", err)
  94. }
  95. }()
  96. _,copyErr := io.Copy(writer, reader)
  97. if copyErr != nil{
  98. return copyErr
  99. }
  100. //修改权限
  101. chmodErr := os.Chmod(dest, mode)
  102. if chmodErr != nil{
  103. return chmodErr
  104. }
  105. return nil
  106. }
  107. //CopyDir 复制目录
  108. func (my *Dir) CopyDir(destParentDir string) error{
  109. //遍历目录
  110. err := filepath.Walk(filepath.Join(my.ParentName, my.DirName), func(path string, f os.FileInfo, err error) error {
  111. return my.visit(path, f, err)
  112. })
  113. if err != nil{
  114. return err
  115. }
  116. //create dir
  117. for _, dirName := range my.DirList{
  118. destDir := filepath.Join(destParentDir, dirName.Fname)
  119. err := my.CreateDir(destDir, dirName.Fmode)
  120. if err != nil{
  121. return err
  122. }
  123. }
  124. //create file
  125. for _, fileName := range my.FileList{
  126. destFile := filepath.Join(destParentDir, fileName.Fname)
  127. srcFile := filepath.Join(my.ParentName,fileName.Fname)
  128. err := my.CreateFile(srcFile, destFile, fileName.Fmode)
  129. if err != nil{
  130. return err
  131. }
  132. }
  133. return nil
  134. }

怎么使用呢

  1. //ParentName 存储的是父级目录
  2. //DirName 存储的目录名字
  3. //比如 /app/test/source 则 ParentName是/app/test DirName是source
  4. asSourceDir := models.Dir{ ParentName: "/app/test", DirName:"source"}
  5. //进行复制destDir就是目的目录
  6. endError := asSourceDir.CopyDir(destDir)
  7. if endError != nil{
  8. return HandleException(endError, "copy ansible to git")
  9. }

在这方面Python还是比较好呀

发表评论

表情:
评论列表 (有 0 条评论,417人围观)

还没有评论,来说两句吧...

相关阅读

    相关 golang:切片拷贝

    内置函数copy()可以将一个数组切片复制到另一个数组切片中,如果加入的两个数组切片不一样大,就会按照其中较小的那个数组切片的元素个数进行复制。 copy( dest