github.com/richardwilkes/toolbox@v1.121.0/xio/fs/move.go (about) 1 // Copyright (c) 2016-2024 by Richard A. Wilkes. All rights reserved. 2 // 3 // This Source Code Form is subject to the terms of the Mozilla Public 4 // License, version 2.0. If a copy of the MPL was not distributed with 5 // this file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 // 7 // This Source Code Form is "Incompatible With Secondary Licenses", as 8 // defined by the Mozilla Public License, version 2.0. 9 10 package fs 11 12 import ( 13 "io" 14 "os" 15 16 "github.com/richardwilkes/toolbox/errs" 17 "github.com/richardwilkes/toolbox/xio" 18 ) 19 20 // MoveFile moves a file in the file system or across volumes, using rename if possible, but falling back to copying the 21 // file if not. This will error if either src or dst are not regular files. 22 func MoveFile(src, dst string) (err error) { 23 var srcInfo, dstInfo os.FileInfo 24 srcInfo, err = os.Stat(src) 25 if err != nil { 26 return errs.Wrap(err) 27 } 28 if !srcInfo.Mode().IsRegular() { 29 return errs.Newf("%s is not a regular file", src) 30 } 31 dstInfo, err = os.Stat(dst) 32 if err != nil { 33 if !os.IsNotExist(err) { 34 return errs.Wrap(err) 35 } 36 } else { 37 if !dstInfo.Mode().IsRegular() { 38 return errs.Newf("%s is not a regular file", dst) 39 } 40 if os.SameFile(srcInfo, dstInfo) { 41 return nil 42 } 43 } 44 if os.Rename(src, dst) == nil { 45 return nil 46 } 47 var in, out *os.File 48 out, err = os.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, srcInfo.Mode()) 49 if err != nil { 50 return errs.Wrap(err) 51 } 52 defer func() { 53 if closeErr := out.Close(); closeErr != nil && err == nil { 54 err = closeErr 55 } 56 }() 57 if in, err = os.Open(src); err != nil { 58 err = errs.Wrap(err) 59 return 60 } 61 _, err = io.Copy(out, in) 62 xio.CloseIgnoringErrors(in) 63 if err != nil { 64 err = errs.Wrap(err) 65 return 66 } 67 if err = os.Remove(src); err != nil { 68 err = errs.Wrap(err) 69 } 70 return 71 }