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

作者:shichen2014 时间:2024-04-26 17:21:39 

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

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

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

代码如下:

// 一个简单的目录复制程序:一个独立的 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语言程序设计有所帮助。

标签:GO语言,目录,复制
0
投稿

猜你喜欢

  • Pytorch环境搭建与基本语法

    2021-04-22 21:57:47
  • 解决oracle用户连接失败的解决方法

    2011-01-04 19:35:00
  • php实现的微信分享到朋友圈并记录分享次数功能

    2023-10-17 04:32:14
  • 全网最详细的vscode基础教程

    2022-09-22 08:43:05
  • PHP session有效期问题

    2023-11-23 20:49:10
  • python3中类的继承以及self和super的区别详解

    2023-02-23 20:31:25
  • mysql中的int(10)int(20)分别代表什么意思

    2024-01-20 21:31:30
  • python网络编程之TCP通信实例和socketserver框架使用例子

    2023-02-03 05:53:09
  • 详解Python Socket网络编程

    2022-09-05 14:04:16
  • 基于php socket(fsockopen)的应用实例分析

    2023-11-18 21:38:32
  • python中redis查看剩余过期时间及用正则通配符批量删除key的方法

    2023-08-02 12:12:27
  • 如何安装多版本python python2和python3共存以及pip共存

    2021-03-23 05:08:58
  • 基于Python实现简单学生管理系统

    2021-01-02 18:58:11
  • python实现百万答题自动百度搜索答案

    2021-10-06 03:57:11
  • matplotlib绘制两点间连线的几种方法实现

    2021-07-27 09:02:24
  • 经典mysql连接查询例题

    2024-01-14 17:32:29
  • Centos7下使用yum安装mysql数据库的详细教程(增强版)

    2024-01-13 17:24:52
  • 浅说相册图片详情页面中大图的浏览方式

    2009-02-01 18:34:00
  • python 实现快速生成连续、随机字母列表

    2021-02-20 19:46:45
  • python 如何将数据写入本地txt文本文件的实现方法

    2021-05-02 14:11:52
  • asp之家 网络编程 m.aspxhome.com