Skip to content

os: documentation of Rename doesn't specify the behavior of trying to rename a file to an existing directory #68690

@naughtyGitCat

Description

@naughtyGitCat

Go version

go version go1.22.2 darwin/arm64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/naughtyGitCat/Library/Caches/go-build'
GOENV='/Users/naughtyGitCat/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/naughtyGitCat/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/naughtyGitCat/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.com.cn,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.22.2'
GCCGO='gccgo'
AR='ar'
CC='clang'
CXX='clang++'
CGO_ENABLED='1'
GOMOD='/Users/naughtyGitCat/development/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/8g/_t9d_0693kz1pmsfkcb72hj40000gn/T/go-build3876076188=/tmp/go-build -gno-record-gcc-switches -fno-common'

What did you do?

code in https://go.dev/play/p/GmHflbjn1uG
same as below

// You can edit this code!
// test file move
// file a.conf, dir a.bak, move `a.conf` to `a.bak`
package main

import (
	"fmt"
	"os"
	"os/exec"
)

func moveFileByUnixMove() {
	fmt.Println("now move file to dir by unix mv....")
	_, err := exec.Command("touch", "b.conf").CombinedOutput()
	if err != nil {
		panic(err)
	}
	err = os.Mkdir("b.bak", 0700)
	if err != nil {
		panic(err)
	}
	_, err = exec.Command("mv", "b.conf", "b.bak").CombinedOutput()
	if err != nil {
		panic(err)
	}
	fmt.Println("now check files in dir...")
	dir, err := os.Open("b.bak")
	if err != nil {
		panic(err)
	}
	defer dir.Close()
	names, _ := dir.Readdirnames(2)
	if len(names) > 0 {
		for _, name := range names {
			fmt.Println(fmt.Sprintf("b.bak dir have file: %s", name))
		}
	} else {
		fmt.Println("dir have no files")
	}
}

func moveFileByGoRename() {
	fmt.Println("now move file to dir by go, os.Rename....")
	_, err := exec.Command("touch", "a.conf").CombinedOutput()
	if err != nil {
		panic(err)
	}
	err = os.Mkdir("a.bak", 0700)
	if err != nil {
		panic(err)
	}
	err = os.Rename("a.conf", "a.bak")
	if err != nil {
		fmt.Println(fmt.Sprintf("move file by os.Rename failed, %v", err))
	}
	fmt.Println("now check files in dir...")
	dir, err := os.Open("a.bak")
	if err != nil {
		panic(err)
	}
	defer dir.Close()
	names, _ := dir.Readdirnames(2)
	if len(names) > 0 {
		for _, name := range names {
			fmt.Println(fmt.Sprintf("a.bak dir have file: %s", name))
		}
	} else {
		fmt.Println("dir have no files")
	}
}

func main() {
	moveFileByUnixMove()
	fmt.Println()
	moveFileByGoRename()
}

What did you see happen?

// test file move
// file: a.conf, dir: a.bak, move a.conf to a.bak

program output:

now move file to dir by unix mv....
now check files in dir...
b.bak dir have file: b.conf

now move file to dir by go, os.Rename....
move file by os.Rename failed, rename a.conf a.bak: file exists
now check files in dir...
dir have no files

What did you expect to see?

move file to dir without error, and

now check files in dir...
b.bak dir have file: b.conf

what did you want

add a dedicate os.Move() command just like mv (i know mv is utility of rename), or add comment to os.Rename suggest developer use os.Rename(file.conf, file.bak/file.conf) is this circumstance

Metadata

Metadata

Assignees

No one assigned

    Labels

    DocumentationIssues describing a change to documentation.FixPendingIssues that have a fix which has not yet been reviewed or submitted.FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions