如何在 go 移动文件?

49 天前
 qW7bo2FbzbC0
import (
"os"
)

func main(){
 err := os.Rename("/home/go/v2ex/user.conf", "/home/go/v2ex/bak/userX.20240731")
 fmt.Println(err)
}

问题

复现链接: https://go.dev/play/p/GmHflbjn1uG

1928 次点击
所在节点    Go 编程语言
9 条回复
seth19960929
49 天前
首先, 其次, 然后你的代码改这个就可以了
err = os.Rename("a.conf", "a.bak/a.conf")
seth19960929
49 天前
你理解 mv a.conf a.bak 和 mv a.conf a.bak/ 的区别, 就不会那样写代码了
qW7bo2FbzbC0
49 天前
@seth19960929 可是无论 mv a.conf a.bak 和 mv a.conf a.bak/ 在 unix 下都是相同的表现啊? mv a.conf a.bak 就是把文件移动到目录中
Reficul
49 天前
mv 命令不单单是调用了 rename_at 这个 syscall ,还做了很多别的事情。比如跨 filesystem 的时候,rename_at 会失败,但是 mv 会复制过去再删掉原本的文件。
qW7bo2FbzbC0
49 天前
@seth19960929 这个的确可以解决,用了这个方式,我就不需要用#替代.了
Kumo31
49 天前
即使是 mv 这样看起来很简单的 command tool ,做的工作也比想象中得多,和 syscall 肯定不是一个粒度的,这个 case 里你用 strace 来跟踪下 mv 产生的 syscall 就知道了。

mv 先会尝试去直接 rename 到 dir 这个目录上,但是 syscall 报错 file exists
renameat2(AT_FDCWD, "test-file", AT_FDCWD, "dir", RENAME_NOREPLACE) = -1 EEXIST (File exists)

mv 应该特殊处理了这个错误,第二次会尝试 rename 到 dir/test-file
renameat2(AT_FDCWD, "test-file", AT_FDCWD, "dir/test-file", RENAME_NOREPLACE) = 0
qW7bo2FbzbC0
49 天前
如下语言内置库支持 move
https://docs.python.org/3/library/shutil.html
https://learn.microsoft.com/en-us/dotnet/api/system.io.file.move
https://docs.oracle.com/javase/tutorial/essential/io/move.html

如下语言不支持 move ,但是注释写的很明确
https://doc.rust-lang.org/std/fs/fn.rename.html
On Unix, if from is a directory, to must also be an (empty) directory. If from is not a directory, to must also be not a directory

这是 go 语言的注释
https://pkg.go.dev/os#Rename
Rename renames (moves) oldpath to newpath. If newpath already exists and is not a directory, Rename replaces it. OS-specific restrictions may apply when oldpath and newpath are in different directories. .....
konakona
49 天前
好像不需要了解太多原理……

单纯想告诉你,L:52 应该改为 err = os.Rename("a.conf", "a.bak/a.conf")
konakona
49 天前
在 Go 中,os.Rename() 函数是对 POSIX 标准中 rename() 系统调用的包装。虽然有些系统没有 rename()(比如 macOS ),但 os.Rename()仍然在尽力保持 rename() 包装的调用,为此会用一些当前系统支持的其他命令来达到。

所以它没办法单纯的被理解为 mv 指令。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1061650

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX