Go实现文件复制、移动(cp、mv命令)

两个字:干货

目录

复制文件

方式1:通过内置包文件操作实现

姿势1

姿势2

姿势3

方式2:通过exec包实现

移动文件

方式1:通过内置包文件操作实现

方式2:通过exec包实现

提示


复制文件

方式1:通过内置包文件操作实现

姿势1

func CopyFile(src, dst string) (size int64, err error) {
    fmt.Printf("ready copy '%s' to '%s'\n", src, dst)

    srcFile, err := os.OpenFile(src, os.O_RDONLY, 0644)
    if err != nil {
        err = fmt.Errorf("failed to open source file: %v", err)
        return
    }
    defer srcFile.Close()

    info, err := srcFile.Stat()
    if err != nil {
        err = fmt.Errorf("failed to get file info: %v\n", err)
        return
    }

    size = info.Size()

    if info.IsDir() {
        err = fmt.Errorf("source is a directory, does not support copying directories recursively.")
        return
    }

    dstFile, err := createFile(dst, info)
    if err != nil {
        err = errors.New(fmt.Sprintf("failed to create destination file: %v", err))
        return
    }
    defer dstFile.Close()

    _, err = io.Copy(dstFile, srcFile)
    if err != nil {
        err = fmt.Errorf(fmt.Sprintf("failed to copy file: %v\n", err))
        return
    }

    fmt.Printf("successfully copied '%s' to '%s'\n", src, dst)
    return
}

func createFile(dst string, info os.FileInfo) (*os.File, error) {
    dir := filepath.Dir(dst)
    
    err := os.MkdirAll(dir, os.ModePerm)
    if err != nil {
        return nil, fmt.Errorf("failed to create destination directory: %w", err)
    }

    dstFile, err := os.Create(dst)
    if err != nil {
        return nil, fmt.Errorf("failed to create destination file: %w", err)
    }

    err = dstFile.Chmod(info.Mode())
    if err != nil {
        dstFile.Close()
        return nil, fmt.Errorf("failed to set destination file permissions: %w", err)
    }

    return dstFile, nil
}

姿势2

功能相同,但建议仅应用于小文件:

func CopyFile(src, dest string) error {
	fileInfo, err := os.Stat(src)
	if err != nil {
		return err
	}
	contents, err := os.ReadFile(src)
	if err != nil {
		return err
	}
// 目标文件不存在会自动创建,且权限相同
	err = os.WriteFile(dest, contents, fileInfo.Mode())  
	return err
}

姿势3

func CopyFile(source, dest string) error {
	sf, err := os.Open(source)
	if err != nil {
		return fmt.Errorf("unable to open source file [%s]: %q", source, err)
	}
	defer sf.Close()
	
	fi, err := sf.Stat()
	if err != nil {
		return fmt.Errorf("unable to stat source file [%s]: %q", source, err)
	}

	dir := filepath.Dir(dest)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("unable to create directory [%s]: %q", dir, err)
	}
	
	df, err := os.Create(dest)  // 若待写入文件已存在则清空,不存在则创建
	if err != nil {
		return fmt.Errorf("unable to create destination file [%s]: %q", dest, err)
	}
	defer df.Close()

	_, err = io.Copy(df, sf)
	if err != nil {
		return fmt.Errorf("unable to copy [%s] to [%s]: %q", source, dest, err)
	}

	if err := os.Chmod(dest, fi.Mode()); err != nil {
		return fmt.Errorf("unable to close destination file: %q", err)
	}
	
	return nil
}

方式2:通过exec包实现

封装执行简单命令的函数:

func Exec(name string, args ...string) (outString string, err error) {
    var out bytes.Buffer
    var stderr bytes.Buffer

    cmd := exec.Command(name, args...)
    cmd.Stdout = &out
    cmd.Stderr = &stderr

    err = cmd.Run()
    outString = out.String()
    if err != nil {
        err = fmt.Errorf("exec failed: %v, stderr=%s. name=%s, args=%v.", err, stderr.String(), name, args)
    }

    return
}

使用:

_, err = Exec("cp", src, dst)

即可完成文件复制。

移动文件

方式1:通过内置包文件操作实现

func Move(src, dst string) error {
    return os.Rename(src, dst)
}

方式2:通过exec包实现

_, err = Exec("mv", src, dst)

提示

目标目录不存在时,通过exec.Command的方式执行cp、mv会报错,因此需要提前准备好目的目录。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ProblemTerminator

您的鼓励将是作者最大的动力哦!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值