Last active
November 22, 2024 02:38
-
-
Save var23rav/23ae5d0d4d830aff886c3c970b8f6c6b to your computer and use it in GitHub Desktop.
GoLang: os.Rename() give error "invalid cross-device link" for Docker container with Volumes. MoveFile(source, destination) will work moving file between folders
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ( | |
"fmt" | |
"io" | |
"os" | |
) | |
/* | |
GoLang: os.Rename() give error "invalid cross-device link" for Docker container with Volumes. | |
MoveFile(source, destination) will work moving file between folders | |
*/ | |
func MoveFile(sourcePath, destPath string) error { | |
inputFile, err := os.Open(sourcePath) | |
if err != nil { | |
return fmt.Errorf("Couldn't open source file: %s", err) | |
} | |
outputFile, err := os.Create(destPath) | |
if err != nil { | |
inputFile.Close() | |
return fmt.Errorf("Couldn't open dest file: %s", err) | |
} | |
defer outputFile.Close() | |
_, err = io.Copy(outputFile, inputFile) | |
inputFile.Close() | |
if err != nil { | |
return fmt.Errorf("Writing to output file failed: %s", err) | |
} | |
// The copy was successful, so now delete the original file | |
err = os.Remove(sourcePath) | |
if err != nil { | |
return fmt.Errorf("Failed removing original file: %s", err) | |
} | |
return nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A few more notes.
Error comparison:
If one is only targeting a Unix-like system, the check for this error may be better achieved by checking whether the
syscall.Errno
is18
. If one were to use thestrings.Contain
check as written below, in go1.19, the check will be a false negative e.g. on netbsd and darwin, where the error string is "cross-device link" (note, missing "invalid" at start).File types/symbolic links: On Unix-like systems, when the source file is a symbolic link, the rename(2) and renameat(2) syscalls, used by
os.Rename
, will rename the symbolic link itself. In others words, the system calls, and consequentlyos.Rename
, do not follow symbolic links. But infunc moveCrossDevice
, usingos.Open
will always follow symbolic links. Given this, one may likely want to do the following:os.Symlink
, then remove the source file.os.Open
,os.Create
,io.Copy
, then remove the source file.Additionally, one may want to change
os.Stat(source)
, which follows symbolic links, toos.Lstat(source)
, which doesn't follow symbolic links.Error handling: For the
(*os.File).Close
andos.Remove
calls infunc moveCrossDevice
, one may want to handle returned errors.