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还是比较好呀

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值