时值我小病在家休养生息,喜欢跳广场舞的外公来寻求我的帮助,他们跳广场舞是将存有歌曲的U盘插到音响上面,而音响大部分都是只能显示歌曲的索引index,不能直接显示歌曲名,所以为了方便他们会在U盘里面对歌曲进行排序。由于音响是寻址按顺序播放,意思就是在U盘里面的歌曲需要一首一首的按顺序复制过去,而且当对U盘歌曲进行增添的时候又需要按照顺序重新复制一遍,可以说相当麻烦。为了将我从这重复的劳动中解放出来,我用go语言写了一个小工具,本来想着分分钟写完,却没想到踩到了坑。

os包中有一个Rename()函数具有重命名和移动的功能,其函数如下:

func Rename(oldpath, newpath string) error

Rename修改一个文件的名字,移动一个文件。可能会有一些个操作系统特定的限制。

在windows系统下面使用该函数,oldpathnewpath在同一个磁盘/卷下面能正常使用,可我需要将音乐移动到U盘上,当使用这个函数的时候出现了:

The system cannot move the file to a different disk drive.

搜索Githubissues,发现Rename在windows中不能进行跨磁盘/卷操作。

为了实现跨磁盘/卷操作,一种方法是直接调用windows API,于是在windows api docs中搜索到movefileex()函数能够实现该功能,但是在go语言的syscall包中只有movefile()函数,其函数如下:

func MoveFile(from *uint16, to *uint16) (err error)

实现文件移动的函数可以写成:

func movefile(oldpath, newpath string) error { //跨卷移动
from, err := syscall.UTF16PtrFromString(oldpath)
if err != nil {
return err
}
to, err := syscall.UTF16PtrFromString(newpath)
if err != nil {
return err
}
return syscall.MoveFile(from, to)//windows API }

当我们读取oldpath目录里面的文件时调用io/ioutil包的ReadDir()函数可按照文件夹内的排序方式批量读入文件名,其函数实现如下:

func filenamelist(filepath string) []string {
var list []string
rd, err := ioutil.ReadDir(filepath) //遍历目录
if err != nil {
log.Fatal(err)
}
for _, fi := range rd {
if fi.IsDir() {
fmt.Printf("[%s]is dir\n", fi.Name()) } else {
list = append(list, fi.Name())
fmt.Println(filepath + fi.Name())
}
}
return list//返回一个string数组 }

当然也可以普通方式读入文件名然后用sort包进行排序。

下面是完整代码:

package main

import (
"fmt"
"io/ioutil"
"log"
"os"
"syscall"
) func movefile(oldpath, newpath string) error { //跨卷移动
from, err := syscall.UTF16PtrFromString(oldpath)
if err != nil {
return err
}
to, err := syscall.UTF16PtrFromString(newpath)
if err != nil {
return err
}
return syscall.MoveFile(from, to)//windows API }
func filenamelist(filepath string) []string {
var list []string
rd, err := ioutil.ReadDir(filepath) //遍历目录
if err != nil {
log.Fatal(err)
}
for _, fi := range rd {
if fi.IsDir() {
fmt.Printf("[%s]is dir\n", fi.Name()) } else {
list = append(list, fi.Name())
fmt.Println(filepath + fi.Name())
}
}
return list }
func movefilelist(oldpath, newpath string) {
for _, fi := range filenamelist(oldpath) { //移动目录的所有文件
err := movefile(oldpath+fi, newpath+fi)
if err != nil {
log.Fatal(err)
}
fmt.Println(fi + "--Move To -->" + newpath + "--OK!") }
}
func main() {
movefilelist(os.Args[1], os.Args[2])
}

最后在终端中:

Ryan@DESKTO MINGW64 /Go/test (master)
$ go run main.go ~/Desktop/music/ /d/
C:/Users/Ryan/Desktop/music/新建文本文档 (2).txt
C:/Users/Ryan/Desktop/music/新建文本文档.txt
新建文本文档 (2).txt--Move To -->D:/--OK!
新建文本文档.txt--Move To -->D:/--OK!

有了这个脚本,我今后终于可以愉快的帮助我外公了。

转载请注明

go语言 os.Rename() cannot move the file to a different disk drive 怎么办的更多相关文章

  1. python shutil 模块 的剪切文件函数 shutil.movemove(src, dst),换用 os.rename(sourceFile, targetFile)

    Google 一搜python 剪切文件,出来shutil 这模块,网上很多人也跟疯说shutil.move(src, dst)就是用来剪切文件的,结果一试,剪切毛线,文件都复制到另一个文件夹了,源文 ...

  2. 合并静态库出现 can't move temporary file错误

    静态库的制作就不说了很简单,网上也很多例子,这里主要讲下我合并通用静态库时候遇见的坑,在合并前注意.a文件一定要正确,我有一次scheme选了release但是device忘了换,结果怼着两个模拟器静 ...

  3. shutil.copy()、os.walk()、os.rename()实例

    #!/usr/bin/python # -*- coding: UTF-8 -*- import os import shutil Path = "panel/" PNPath = ...

  4. CentOS VSCode调试go语言出现:exec: "gcc": executable file not found in PATH

    CentOS VSCode调试go语言出现:exec: "gcc": executable file not found in PATH 解决方案: 执行如下命令安装GCC,然后重 ...

  5. 【翻译自mos文章】 在错误的从os级别remove掉 trace file 之后,怎么找到该trace file的内容?

    在错误的从os级别remove掉 trace file 之后,怎么找到该trace file的内容? 參考原文: How to Find the Content of Trace File Gener ...

  6. Python os.rename() 方法

    概述 os.rename() 方法用于命名文件或目录,从 src 到 dst,如果dst是一个存在的目录, 将抛出OSError.高佣联盟 www.cgewang.com 语法 rename()方法语 ...

  7. VSCode调试go语言出现:exec: "gcc": executable file not found in %PATH%

    1.问题描述 由于安装VS15 Preview 5,搞的系统由重新安装一次:在用vscdoe编译go语言时,出现以下问题: # odbcexec: "gcc": executabl ...

  8. os.rename 和os.replace

    f1 = open("hello.txt","w") f1.write("hello,my name is bobo.") f1.close ...

  9. C语言基础 (12) 文件的操作 FILE

    课程回顾 结构体基本操作: 结构体类型的定义 // struct为关键字 Stu为自定义标识符 // struct Stu才是结构体类型 // 结构体成员不能在定义类型时赋值 struct Stu { ...

随机推荐

  1. Effective C++(10) 重载赋值操作符时,返回该对象的引用(retrun *this)

    问题聚焦: 这个准则比较简短,但是往往就是这种细节的地方,可以提高你的代码质量. 细节决定成败,让我们一起学习这条重载赋值操作符时需要遵守的准则吧. 还是以一个例子开始: Demo // 连锁赋值 x ...

  2. OpenCV&&python_图像平滑(Smoothing Images)

    Goals 学习用不同低通滤波方法模糊图像(Blur imagess with various low pass filter) 用用定制的滤波器处理图像(Apply custom-made filt ...

  3. 安装批量装机工具cobbler过程

    首先想到的自然是yum install cobbler,结果找不到这个包,又懒得去官网下源码安装,于是乎想到增加第三方yum源,之后继续yum install cobbler,搞定. 然后启动cobb ...

  4. java多态-向上转型和向下转型

    向上转型:符合“is a”,是安全的,子类向上到父类,多余的属性和方法会丢弃 向下转型:不安全的,用instanceof提前判断一下,以免抛出异常 instanceof用法: result = obj ...

  5. Bootstrap3.0和bootstrap2.x的区别

    bootstrap已经推出了3.0的新版,看起来2.3.x版本也不会再更新了.那么bootstrap 2.3版与3.0版的区别在哪里呢?下面我们就来介绍一下. Bootstrap 3.0增加了一些新的 ...

  6. 转一篇shell中关于各种括号的讲解

    shell中各种括号的作用().(()).[].[[]].{} 一.小括号,圆括号()1.单小括号 ()   ①命令组.括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的 ...

  7. js实现简单的评论和回复功能(数组版)

    var method={ getDate:function (a,b){ //获取当前日期 //a表示年月日直接的分隔符,b表示时分秒之间的分隔符 var dateStr="", ...

  8. 【RabbitMQ】1、安装

    1.  下载 下载地址:http://www.rabbitmq.com/download.html 2.  windows下安装 2.1. 安装Erlang 下载:http://www.erlang. ...

  9. Java对文件的读取方式以及它们的优缺点

    Java常用的对文件的读取方式基本包括: BufferedReader -> readLine(): 按行读取文件,直到读取内容==null FileInputStream -> read ...

  10. (六)Linux下的压缩命令

    ======================================================================================== .zip格式的压缩和解 ...