GO语言实现简单的目录复制功能

 更新时间:2020年5月1日 09:42  点击:2073

本文实例讲述了GO语言实现简单的目录复制功能。分享给大家供大家参考。具体实现方法如下:

创建一个独立的 goroutine 遍历文件,主进程负责写入数据。程序会复制空目录,也可以设置只复制以 ".xx" 结尾的文件。
严格来说这不是复制文件,而是写入新文件。因为这个程序是创建新文件,然后写入复制数据的。我们一般的 copy 命令是不会修改文件的 ctime(change time) 状态的。

代码如下:

复制代码 代码如下:
// 一个简单的目录复制程序:一个独立的 goroutine 遍历目录,主进程负责将数据写入新目录。
// 2014-11-02 Bing.L
package main

import (
 "io"
 "log"
 "os"
 "path/filepath"
 "strings"
)

type FileInfo struct {
 RelPath string
 Size    int64
 IsDir   bool
 Handle  *os.File
}

//复制文件数据
func ioCopy(srcHandle *os.File, dstPth string) (err error) {
 dstHandle, err := os.OpenFile(dstPth, os.O_CREATE|os.O_WRONLY, os.ModePerm)
 if err != nil {
  return err
 }

 defer srcHandle.Close()
 defer dstHandle.Close()

 _, err = io.Copy(dstHandle, srcHandle)
 return err
}

//遍历目录,将文件信息传入通道
func WalkFiles(srcDir, suffix string, c chan<- *FileInfo) {
 suffix = strings.ToUpper(suffix)

 filepath.Walk(srcDir, func(f string, fi os.FileInfo, err error) error { //遍历目录
  if err != nil {
   log.Println("[E]", err)
  }

  fileInfo := &FileInfo{}
  if strings.HasSuffix(strings.ToUpper(fi.Name()), suffix) { //匹配文件
   if fh, err := os.OpenFile(f, os.O_RDONLY, os.ModePerm); err != nil {
    log.Println("[E]", err)
   } else {
    fileInfo.Handle = fh
    fileInfo.RelPath, _ = filepath.Rel(srcDir, f) //相对路径
    fileInfo.Size = fi.Size()
    fileInfo.IsDir = fi.IsDir()
   }

   c <- fileInfo
  }
 })
 close(c) //遍历完成,关闭通道
}

//写目标文件
func WriteFiles(dstDir string, c <-chan *FileInfo) {
 if err := os.Chdir(dstDir); err != nil { //切换工作路径
  log.Fatalln("[F]", err)
 }

 for f := range c {
  if fi, err := os.Stat(f.RelPath); os.IsNotExist(err) { //目标不存在
   if f.IsDir {
    if err := os.MkdirAll(f.RelPath, os.ModeDir); err != nil {
     log.Println("[E]", err)
    }
   } else {
    if err := ioCopy(f.Handle, f.RelPath); err != nil {
     log.Println("[E]", err)
    } else {
     log.Println("[I] CP:", f.RelPath)
    }
   }
  } else if !f.IsDir { //目标存在,而且源不是一个目录

   if fi.IsDir() != f.IsDir { //检查文件名被目录名占用冲突
    log.Println("[E]", "filename conflict:", f.RelPath)

   } else if fi.Size() != f.Size { //源和目标的大小不一致时才重写
    if err := ioCopy(f.Handle, f.RelPath); err != nil {
     log.Println("[E]", err)
    } else {
     log.Println("[I] CP:", f.RelPath)
    }
   }
  }
 }
}

func main() {
 files_ch := make(chan *FileInfo, 100)

 go WalkFiles("E:\\study", ".doc", files_ch) //在一个独立的 goroutine 中遍历文件
 WriteFiles("E:\\study.bak", files_ch)
}

希望本文所述对大家的GO语言程序设计有所帮助。

[!--infotagslink--]

相关文章

  • 解决Pycharm的项目目录突然消失的问题

    今天小编就为大家分享一篇解决Pycharm的项目目录突然消失的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-04-22
  • Go语言压缩和解压缩tar.gz文件的方法

    这篇文章主要介绍了Go语言压缩和解压缩tar.gz文件的方法,实例分析了使用Go语言压缩文件与解压文件的技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-05-03
  • MySQL快速复制数据库数据表的方法

    某些时候,例如为了搭建一个测试环境,或者克隆一个网站,需要复制一个已存在的mysql数据库。使用以下方法,可以非常简单地实现。假设已经存在的数据库名字叫db1,想要复制一份,命名为newdb。步骤如下:1. 首先创建新的数据库newd...2015-10-21
  • C#路径,文件,目录及IO常见操作汇总

    这篇文章主要介绍了C#路径,文件,目录及IO常见操作,较为详细的分析并汇总了C#关于路径,文件,目录及IO常见操作,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • docker 启动elasticsearch镜像,挂载目录后报错的解决

    这篇文章主要介绍了docker 启动 elasticsearch镜像,挂载目录后报错的解决,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-11-20
  • idea out目录与target目录的区别详解

    这篇文章主要介绍了idea out目录与target目录的区别详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-08
  • C#获得程序的根目录以及判断文件是否存在的实例讲解

    今天小编大家分享一篇C#获得程序的根目录以及判断文件是否存在的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-06-25
  • PHP递归创建多级目录

    我的第一个感觉就是用递归创建,具体思路如下: function Directory($dir){    if(is_dir($dir) || @mkdir($dir,0777)){ //查看目录是否已经存在或尝试创建,加一个@抑制符号是因为第一次创建失败,会报一个“父目录不存...2015-11-08
  • 利用Node.js获取项目根目录的小技巧

    这篇文章介绍的是一个小技巧来获取node.js项目根目录,这个技巧非常实用。有需要的朋友们可以参考借鉴,下面来一起看看吧。...2016-10-02
  • C# 复制与删除文件的实现方法

    这篇文章主要介绍了C# 复制与删除文件的实现方法的相关资料,希望通过本文能帮助到大家,让大家理解掌握这部分内容,需要的朋友可以参考下...2020-06-25
  • JavaScript深度复制(deep clone)的实现方法

    本文给大家介绍JavaScript深度复制(deep clone)的实现方法,涉及到js深度复制相关知识,本文介绍的非常详细,特此分享脚本之家平台供大家参考...2016-02-21
  • percona-toolkit对MySQL的复制和监控类操作教程

    复制类工具 1. pt-heartbeat 功能介绍: 监控mysql复制延迟 用法介绍: pt-heartbeat [OPTION...] [DSN] --update|--monitor|--check|--stop 测量复制落后主mysql或者主PostgreSQL多少时间,你可以使用这个脚本去更新主或...2015-11-24
  • C#中数组初始化与数组元素复制的方法

    这篇文章主要介绍了C#中数组初始化与数组元素复制的方法,涉及C#中数组的创建、初始化及使用Array.Copy方法复制数组元素的技巧,需要的朋友可以参考下...2020-06-25
  • python import 上级目录的导入

    这篇文章主要介绍了python import 上级目录的导入,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-03
  • 解决docker挂载的目录无法读写问题

    这篇文章主要介绍了解决docker挂载的目录无法读写问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-19
  • C++递归删除一个目录实例

    这篇文章主要介绍了C++递归删除一个目录的实现方法,涉及到目录的操作及递归算法的应用,需要的朋友可以参考下...2020-04-25
  • mysql(master/slave)主从复制原理及配置图文详解

    这篇文章主要介绍了mysql(masterslave)主从复制原理及配置图文详解,以前脚本之家小编发过相关的内容,但这么好的非常少见特分享一下,需要的朋友可以参考下...2016-06-12
  • step by step配置mysql复制的具体方法

    采用全库复制的方案,方便管理mysql 5.5 + rhel5.810.4.11.12 master10.4.11.13 slave---Master端设置1, 创建复制帐号,需要复制和slave权限mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO repl@'10....2013-10-04
  • go语言使用RC4加密的方法

    这篇文章主要介绍了go语言使用RC4加密的方法,实例分析了RC4加密的技巧与实现方法,具有一定参考借鉴价值,需要的朋友可以参考下...2020-05-07
  • Go语言图片处理和生成缩略图的方法

    这篇文章主要介绍了Go语言图片处理和生成缩略图的方法,涉及Go语言针对图片操作的技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-05-03