import (
"os"
)
func main(){
err := os.Rename("/home/go/v2ex/user.conf", "/home/go/v2ex/bak/userX.20240731")
fmt.Println(err)
}
1
seth19960929 114 天前
首先, 其次, 然后你的代码改这个就可以了
err = os.Rename("a.conf", "a.bak/a.conf") |
2
seth19960929 114 天前
你理解 mv a.conf a.bak 和 mv a.conf a.bak/ 的区别, 就不会那样写代码了
|
3
qW7bo2FbzbC0 OP @seth19960929 可是无论 mv a.conf a.bak 和 mv a.conf a.bak/ 在 unix 下都是相同的表现啊? mv a.conf a.bak 就是把文件移动到目录中
|
4
Reficul 114 天前
mv 命令不单单是调用了 rename_at 这个 syscall ,还做了很多别的事情。比如跨 filesystem 的时候,rename_at 会失败,但是 mv 会复制过去再删掉原本的文件。
|
5
qW7bo2FbzbC0 OP @seth19960929 这个的确可以解决,用了这个方式,我就不需要用#替代.了
|
6
Kumo31 114 天前 2
即使是 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 |
7
qW7bo2FbzbC0 OP 如下语言内置库支持 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. ..... |
8
konakona 114 天前
好像不需要了解太多原理……
单纯想告诉你,L:52 应该改为 err = os.Rename("a.conf", "a.bak/a.conf") |
9
konakona 114 天前
在 Go 中,os.Rename() 函数是对 POSIX 标准中 rename() 系统调用的包装。虽然有些系统没有 rename()(比如 macOS ),但 os.Rename()仍然在尽力保持 rename() 包装的调用,为此会用一些当前系统支持的其他命令来达到。
所以它没办法单纯的被理解为 mv 指令。 |