os.Rename是Go中移动和重命名文件的唯一标准操作,底层调用系统rename(2),原子、高效;跨文件系统需手动copy+remove,并处理目录创建、权限、占用等隐式约束。
Go 没有单独的 MoveFile 或 RenameFile 函数,os.Rename 就是你要用的全部——它既可重命名,也可跨目录移动,只要源和目标在同一个文件系统(即同一挂载点)。底层直接调用系统 rename(2) 系统调用,快、轻量、原子:不会出现“只移了一半”的中间状态。
os.Rename("a.txt", "b.txt") → 同目录重命名os.Rename("data/log.txt", "archive/log_2026.txt") → 移动并改名(同盘)archive/)必须已存在,否则报 no such file or directory
当 os.Rename 返回 syscall.EXDEV(Linux/macOS)或类似设备错误(Windows 跨卷如 C:\ → D:\),说明源和目标不在同一挂载点。此时必须自己实现“复制内容 → 同步元数据 → 删除原文件”流程。
os.Open 和 os.Create 配合 io.Copy 复制内容os.Chmod(dst, info.Mode()) 和 os.Chtimes(dst, info.ModTime(), info.ModTime()) 同步权限与时间戳os.Remove(oldpath);任一环节失败,应保留原文件,并清理已写入的目标文件(避免残留)os.MkdirAll(filepath.Dir(newpath), 0755) 确保目标目录存在90% 的失败不是函数写错,而是环境没兜住。这些检查不能省:
os.IsNotExist(err),需提前 os.Stat(oldpath) 
os.MkdirAll(filepath.Dir(newpath), 0755),不能指望 os.Rename 自动建Access is denied;可先 os.Remove(newpath)(如果允许覆盖),或 os.Chmod(newpath, 0666) 解除只读"dir" + "/" + "file.txt",一律用 filepath.Join("dir", "file.txt") 防止 Windows/Linux 斜杠不一致遍历目录重命名多个文件时,边 os.ReadDir 边 os.Rename 很危险:比如把 1.txt → 2.txt,接着又把 2.txt → 3.txt,就丢了一个文件。
os.ReadDir 收集所有 fs.DirEntry,生成完整的新路径列表,再统一执行 os.Rename
fmt.Sprintf 生成新名,但注意 filepath.Base 和 filepath.Ext 提取扩展名更可靠真正麻烦的从来不是 os.Rename 本身,而是它背后那套隐式约束:挂载点是否一致、目录是否存在、文件是否被锁、权限是否足够、路径是否合法。写一次 rename 很快,但让它在各种机器上都稳,得把每条错误分支都当成必经之路来对待。