欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-12-07 20:54:04
本文实例讲述了go语言实现简单的目录复制功能。分享给大家供大家参考。具体实现方法如下: 创建一个独立的 goroutine 遍历文件,主进程负责写入数据。程序会复制空目录...

本文实例讲述了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语言程序设计有所帮助。