Skip to content

Releases: IBAS0742/kaoyan

文件备份工具

15 Nov 09:38
cbafa16
Compare
Choose a tag to compare

大概的使用方法如下

使用方法: sync [-tar=] [-from=] [-to=] [-help=] [-exclude=]

Options:
  -exclude string
        排除文件,只在 [tar=dir] 时有效
  -from string
        源文件位置
  -help
        帮助文档
  -tar string
        file 或 dir 表示同步的文件是[文件]或[文件夹]
  -to string
        同步到的位置

exclude 是指定一个文件,文件中每行对应一个文件夹路径
例如 sync -t dir -f d:\a -t e:\a -e d:\a\exclude.txt
d:\a\exclude.txt 内容如下三行时
path=.git
path=.idea
exte=.exe
  • 备份时,通过检查文件 MD5 的值来判断一个文件是否需要被覆盖

  • 代码如下

package main

import (
	"crypto/md5"
	"errors"
	"flag"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
	"sunibas.cn/go_utils/utils/DirAndFile"
)

var (
	tar string
	pathFrom string
	pathTo string
	help bool
	ok bool
	errMessage string
	excludeFile string
	excludePath []string
	excludeExt []string
)

func usage()  {
	if len(errMessage) != 0 {
		fmt.Fprint(os.Stderr,"参数错误\r\n" + errMessage)
	}
	fmt.Fprintf(os.Stderr, `sync_ibas version: sync/1.0.0
使用方法: sync_ibas [-tar=] [-from=] [-to=] [-help=] [-exclude=]

Options:
`)
	flag.PrintDefaults()
	fmt.Fprintf(os.Stderr, `
exclude 是指定一个文件,文件中每行对应一个文件夹路径
例如 sync_ibas -t dir -f d:\a -t e:\a -e d:\a\exclude.txt
d:\a\exclude.txt 内容如下三行时
path=.git
path=.idea
exte=.exe
将不会复制 [d:\a\.git] 和 [d:\a\.idea] 两个文件夹和以 [.exe] 结尾的文件
`);
}

func init() () {
	ok = true
	flag.StringVar(&tar,"tar","","file 或 dir 表示同步的文件是[文件]或[文件夹]")
	flag.StringVar(&pathFrom,"from","","源文件位置")
	flag.StringVar(&pathTo,"to","","同步到的位置")
	flag.BoolVar(&help,"help",false,"帮助文档")
	flag.StringVar(&excludeFile,"exclude","","排除文件,只在 [tar=dir] 时有效")
	flag.Usage = usage
}

func checkArgs() {
	if help {
		ok = false
	} else {
		if tar != "file" && tar != "dir" {
			ok = false
			errMessage += "tar 是必要的\r\n"
		}
		if pathFrom == "" {
			errMessage += "from 是必要的\r\n"
		}
		if pathTo == "" {
			errMessage += "to 是必要的\r\n"
		}
	}
}

func getMd5(fpath string) string {
	f, err := os.Open(fpath)
	if err != nil {
		fmt.Println("Open", err)
		return ""
	}

	defer f.Close()

	md5hash := md5.New()
	if _, err := io.Copy(md5hash, f); err != nil {
		fmt.Println("Copy", err)
		return ""
	}
	x := md5hash.Sum(nil)
	md5_s := ""
	for _,b := range x {
		md5_s += strconv.FormatInt(int64(b),16)
	}
	//md5hash.Sum(nil)
	return md5_s
}

func main() {
	flag.Parse()
	checkArgs()

	if !ok {
		flag.Usage()
	} else {
		if tar == "file" {
			syncFile(pathFrom,pathTo)
		} else {
			syncDir()
		}
	}

	//md5_0 := getMd5("D:\\codes\\文档\\HP C3000刀片机操作.docx")
	//md5_1 := getMd5("D:\\codes\\文档\\77ce515f9cf940daf72da6c30e5e7cb.jpg")
	//md5_2 := getMd5("Z:\\jiayu\\文档\\77ce515f9cf940daf72da6c30e5e7cb.jpg")
}

func checkFileExist(filePath string) (bool,error) {
	if t,e := DirAndFile.PathExistsAndType(filePath);
		e == nil {
		if t == DirAndFile.File {
			return true,nil
		} else if t == DirAndFile.NoExist {
			return false,nil
		} else {
			return false,errors.New("不是文件")
		}
	} else {
		return false,e
	}
}

func syncFile(from,to string)  {
	fmt.Printf("开始尝试将[%s]同步到[%s]\r\n",from,to)
	if exist,err := checkFileExist(from);err == nil {
		if exist {
			if exist1,err1 := checkFileExist(to);err1 == nil {
				// 文件存在则判断 md5,不存在则直接复制即可
				if exist1 {
					fmt.Printf("文件[%s]存在",to)
					md5_0 := getMd5(from)
					md5_1 := getMd5(to)
					// md5 一致则事情完成
					if md5_1 == md5_0 {
						fmt.Printf(",并且 md5 一致,不需要同步\r\n")
						return
					} else {
						fmt.Printf(",并且 md5 不一致")
					}
					// md5 不一致,直接删掉然后 if 外直接复制即可
					err2 := os.Remove(to)
					if err2 != nil {
						fmt.Printf("删除 [%s] 发生错误\r\n%s\r\n", to, err1.Error())
					}
				} else {
					fmt.Printf("文件[%s]不存在",to)
				}
				fmt.Printf(",开始复制文件\r\n")
				DirAndFile.CopyFile(from,to)
				fmt.Printf(",文件[%s]复制完成\r\n",to)
			} else {
				fmt.Printf("文件 [%s] 有问题\r\n%s\r\n",to,err1.Error())
			}
		} else {
			fmt.Printf("文件 [%s] 不存在",from)
		}
	} else {
		fmt.Printf("文件 [%s] 有问题\r\n%s\r\n",from,err.Error())
	}
}

// 在路径结尾加 / 或 \
func toRightPath() {
	rep := "\\"
	if DirAndFile.Filepath_Separator == "\\" {
		rep = "/"
	}
	pathFrom = strings.Replace(pathFrom,rep,DirAndFile.Filepath_Separator,-1)
	sp := pathFrom[len(pathFrom) - 1]
	if sp != DirAndFile.Filepath_Separator[0] {
		pathFrom += DirAndFile.Filepath_Separator
	}
	pathTo = strings.Replace(pathTo,rep,DirAndFile.Filepath_Separator,-1)
	sp = pathTo[len(pathTo) - 1]
	if sp != DirAndFile.Filepath_Separator[0] {
		pathTo += DirAndFile.Filepath_Separator
	}
}

func checkPath() error {
	if t,e := DirAndFile.PathExistsAndType(pathFrom);
	 nil == e {
	 	if t != DirAndFile.Dir {
	 		return errors.New(pathFrom + "不存在或不是文件夹")
		} else {
			if t1,e1 := DirAndFile.PathExistsAndType(pathTo);
				nil == e1 {
					if (t1 == DirAndFile.File) {
						return errors.New(pathTo + "不能是一个文件夹")
					} else if (t1 == DirAndFile.Dir) {
						return nil
					} else {
						os.Mkdir(pathTo,os.ModePerm)
						return nil
					}
			} else {
					return e1
			}
		}
	} else {
	 	return e
	}
}

func checkPathAndCreate(npath string) error {
	if t1,e1 := DirAndFile.PathExistsAndType(npath);
		nil == e1 {
		if (t1 == DirAndFile.File) {
			return errors.New(npath + "不能是一个文件夹")
		} else if (t1 == DirAndFile.Dir) {
			return nil
		} else {
			os.Mkdir(npath,os.ModePerm)
			return nil
		}
	} else {
		return e1
	}
}

func readExcludeFile()  {
	if len(excludeFile) != 0 {
		if exist,err := checkFileExist(excludeFile);err == nil {
			if exist {
				excludePath = DirAndFile.ReadAsFileAsLine(excludeFile)
				for ind,ep := range excludePath {
					if len(ep) > 5 && ep[0:5] == "path=" {
						excludePath[ind] = pathFrom + ep[5:]
					} else if len(ep) > 5 && ep[0:5] == "exte=" {
						excludeExt = append(excludeExt,ep[5:])
					}
				}
			} else {
				fmt.Fprint(os.Stderr,"exclude [%s] 文件不存在\r\n",excludeFile)
			}
		} else {
			fmt.Fprint(os.Stderr,"读取 exclude [%s] 文件出错\r\n%s\r\n",excludeFile,err.Error())
		}
	}
}

func syncDir() {
	if err := checkPath();err != nil {
		fmt.Print(err.Error())
		return
	}
	toRightPath()
	readExcludeFile()
	fs,_ := DirAndFile.FilePathWalkDir(pathFrom)
	for _,f := range fs {
		if f.File {
			if f.Name[0] == '~' { continue }
			nfile := pathTo + f.RPath
			fok := true
			for _,ep := range excludePath {
				if len(f.FullPath) >= len(ep) && f.FullPath[0:len(ep)] == ep {
					fok = false
					break
				}
			}
			if fok {
				for _,ee := range excludeExt {
					if len(f.Name) > len(ee) && f.Name[len(f.Name) - len(ee):] == ee {
						fok = false
						break
					}
				}
			}
			if fok {
				syncFile(f.FullPath,nfile)
			} else {
				fmt.Printf("文件[%s]被排除\r\n",nfile)
			}
		} else {
			npath := pathTo + f.RPath
			fok := true
			for _,ep := range excludePath {
				if len(f.FullPath) >= len(ep) && f.FullPath[0:len(ep)] == ep {
					fok = false
					break
				}
			}
			if fok {
				if cpacErr := checkPathAndCreate(npath);cpacErr != nil {
					fmt.Fprintf(os.Stderr,"检查路径[%s]发生错误\r\n%s\r\n",npath,cpacErr.Error())
					excludePath = append(excludePath,npath)
				}
			}
		}
	}
}

F-Secure Freedome VPN 2.28.5979.0.exe

28 Oct 03:47
cbafa16
Compare
Choose a tag to compare

一个超快的梯子

试用5天后重新安装即可

getPrj

21 Oct 02:24
cbafa16
Compare
Choose a tag to compare

获取 tif 和 prj 的投影信息
视频

redis desktop

20 Oct 03:48
cbafa16
Compare
Choose a tag to compare

redis 可视化管理工具
好像是被下架了
没安装,现在没有截图可以提供,应该还是能用的吧

xml_notepadxml_notepad

20 Oct 03:44
cbafa16
Compare
Choose a tag to compare

xml 查看编辑器

TreeSizePortable

20 Oct 03:43
cbafa16
Compare
Choose a tag to compare

树形看目录大小

depends

20 Oct 03:33
cbafa16
Compare
Choose a tag to compare

用于查看c++依赖

UltraISO

20 Oct 03:32
cbafa16
Compare
Choose a tag to compare

用于刻录iso,常用于制作启动盘

oCam_Portable

20 Oct 03:31
cbafa16
Compare
Choose a tag to compare

可以录制屏幕为 gif,但是打开好慢啊

TS助手3.52

20 Oct 03:28
cbafa16
Compare
Choose a tag to compare

可以用于下载 m3u8 视频和合并 ts