GO语言实现简单的目录复制功能
本文实例讲述了go语言实现简单的目录复制功能。分享给大家供大家参考。具体实现方法如下:
创建一个独立的 goroutine 遍历文件,主进程负责写入数据。程序会复制空目录,也可以设置只复制以 ".xx" 结尾的文件。
严格来说这不是复制文件,而是写入新文件。因为这个程序是创建新文件,然后写入复制数据的。我们一般的 copy 命令是不会修改文件的 ctime(change time) 状态的。
代码如下:
// 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语言程序设计有所帮助。
上一篇: 朱满月为什么会被送入尼姑庵?真相是什么
下一篇: 让IIS6支持FLV和RMVB格式方法