golang拷贝目录(持续更新中)
思路
首先遍历源目录,将所有的目录和文件分别存储在两个切片中,然后先创建所有的目录,然后在创建所有的文件。
目前不会处理连接文件
上代码
package models
import (
"bufio"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
//WalkFile 文件对象
type WalkFile struct{
Fname string
Fmode os.FileMode
}
//Dir 目录对象
type Dir struct {
//父目录
ParentName string
//目录的名字
DirName string
//目录下所有的目录
DirList []WalkFile
//目录下所有文件
FileList []WalkFile
//文件已经存在时 是否删除
FileDelSign bool
}
//visit 浏览文件 区分为目录和文件
func(my *Dir) visit(path string, f os.FileInfo, err error) error {
tmpPath := strings.Replace(path, my.ParentName, "",1)
if f == nil {
return err
}
if f.IsDir(){
my.DirList = append(my.DirList, WalkFile{ Fname: tmpPath, Fmode: f.Mode()})
}else if (f.Mode() & os.ModeSymlink) > 0 {
linkError := "!!! ERROR Do not support symbol link"
fmt.Println(linkError)
return errors.New(linkError)
}else{
my.FileList= append(my.FileList, WalkFile{ Fname: tmpPath, Fmode: f.Mode()})
}
return nil
}
//CreateDir 创建目录
func (my *Dir) CreateDir(dest string, mode os.FileMode) error{
//如果目录存在就直接返回
if _,err:=os.Stat(dest); err!=nil{
mkErr := os.MkdirAll(dest, mode)
if mkErr != nil{
return mkErr
}
}
return nil
}
//CreateFile 创建文件
func (my *Dir) CreateFile(sr string, dest string, mode os.FileMode) error{
//判断文件是否存在,如果存在根据FileDelSign决定是否删除
if _,err:=os.Stat(dest); err==nil{
if my.FileDelSign{
if rError := os.Remove(dest); rError != nil {
return rError
}
} else {
return nil
}
}
//拷贝文件
srcFile, err := os.Open(sr)
if err != nil {
return err
}
defer func() {
err := srcFile.Close()
if err!=nil{
fmt.Printf("close file failed %v\n", err)
}
}()
//通过srcFile,获取到READER
reader := bufio.NewReader(srcFile)
//打开dstFileName
dstFile, err := os.OpenFile(dest, os.O_WRONLY|os.O_CREATE, mode)
if err != nil {
return err
}
//通过dstFile,获取到WRITER
writer := bufio.NewWriter(dstFile)
//writer.Flush()
defer func() {
err := dstFile.Close()
if err!=nil{
fmt.Printf("close file failed %v\n", err)
}
}()
_,copyErr := io.Copy(writer, reader)
if copyErr != nil{
return copyErr
}
//修改权限
chmodErr := os.Chmod(dest, mode)
if chmodErr != nil{
return chmodErr
}
return nil
}
//CopyDir 复制目录
func (my *Dir) CopyDir(destParentDir string) error{
//遍历目录
err := filepath.Walk(filepath.Join(my.ParentName, my.DirName), func(path string, f os.FileInfo, err error) error {
return my.visit(path, f, err)
})
if err != nil{
return err
}
//create dir
for _, dirName := range my.DirList{
destDir := filepath.Join(destParentDir, dirName.Fname)
err := my.CreateDir(destDir, dirName.Fmode)
if err != nil{
return err
}
}
//create file
for _, fileName := range my.FileList{
destFile := filepath.Join(destParentDir, fileName.Fname)
srcFile := filepath.Join(my.ParentName,fileName.Fname)
err := my.CreateFile(srcFile, destFile, fileName.Fmode)
if err != nil{
return err
}
}
return nil
}
怎么使用呢
//ParentName 存储的是父级目录
//DirName 存储的目录名字
//比如 /app/test/source 则 ParentName是/app/test DirName是source
asSourceDir := models.Dir{ ParentName: "/app/test", DirName:"source"}
//进行复制destDir就是目的目录
endError := asSourceDir.CopyDir(destDir)
if endError != nil{
return HandleException(endError, "copy ansible to git")
}
在这方面Python还是比较好呀
还没有评论,来说两句吧...