在windows下用go語言寫跨卷批量移動小工具
阿新 • • 發佈:2018-11-28
時值我小病在家休養生息,喜歡跳廣場舞的外公來尋求我的幫助,他們跳廣場舞是將存有歌曲的U盤插到音響上面,而音響大部分都是隻能顯示歌曲的索引index
,不能直接顯示歌曲名,所以為了方便他們會在U盤裡面對歌曲進行排序。由於音響是定址按順序播放,意思就是在U盤裡面的歌曲需要一首一首的按順序複製過去,而且當對U盤歌曲進行增添的時候又需要按照順序重新複製一遍,可以說相當麻煩。為了將我從這重複的勞動中解放出來,我用go語言寫了一個小工具,本來想著分分鐘寫完,卻沒想到踩到了坑。
在os
包中有一個Rename()
函式具有重新命名和移動的功能,其函式如下:
func Rename(oldpath, newpath string) error
Rename修改一個檔案的名字,移動一個檔案。可能會有一些個作業系統特定的限制。
在windows系統下面使用該函式,oldpath
和newpath
在同一個磁碟/卷下面能正常使用,可我需要將音樂移動到U盤上,當使用這個函式的時候出現了:
The system cannot move the file to a different disk drive.
搜尋Github
的issues,發現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])
}
最後在終端中:
[email protected] 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!
有了這個指令碼,我今後終於可以愉快的幫助我外公了。
轉載請註明