mirror of
				https://github.com/bolucat/Archive.git
				synced 2025-10-31 20:03:10 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			131 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			131 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package fileutils
 | |
| 
 | |
| import (
 | |
| 	"io"
 | |
| 	"os"
 | |
| 	"path"
 | |
| 	"path/filepath"
 | |
| 
 | |
| 	"github.com/spf13/afero"
 | |
| 
 | |
| 	"github.com/filebrowser/filebrowser/v2/files"
 | |
| )
 | |
| 
 | |
| // MoveFile moves file from src to dst.
 | |
| // By default the rename filesystem system call is used. If src and dst point to different volumes
 | |
| // the file copy is used as a fallback
 | |
| func MoveFile(fs afero.Fs, src, dst string) error {
 | |
| 	if fs.Rename(src, dst) == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 	// fallback
 | |
| 	err := Copy(fs, src, dst)
 | |
| 	if err != nil {
 | |
| 		_ = fs.Remove(dst)
 | |
| 		return err
 | |
| 	}
 | |
| 	if err := fs.RemoveAll(src); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // CopyFile copies a file from source to dest and returns
 | |
| // an error if any.
 | |
| func CopyFile(fs afero.Fs, source, dest string) error {
 | |
| 	// Open the source file.
 | |
| 	src, err := fs.Open(source)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	defer src.Close()
 | |
| 
 | |
| 	// Makes the directory needed to create the dst
 | |
| 	// file.
 | |
| 	err = fs.MkdirAll(filepath.Dir(dest), files.PermDir)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	// Create the destination file.
 | |
| 	dst, err := fs.OpenFile(dest, os.O_RDWR|os.O_CREATE|os.O_TRUNC, files.PermFile)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	defer dst.Close()
 | |
| 
 | |
| 	// Copy the contents of the file.
 | |
| 	_, err = io.Copy(dst, src)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	// Copy the mode
 | |
| 	info, err := fs.Stat(source)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	err = fs.Chmod(dest, info.Mode())
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // CommonPrefix returns common directory path of provided files
 | |
| func CommonPrefix(sep byte, paths ...string) string {
 | |
| 	// Handle special cases.
 | |
| 	switch len(paths) {
 | |
| 	case 0:
 | |
| 		return ""
 | |
| 	case 1:
 | |
| 		return path.Clean(paths[0])
 | |
| 	}
 | |
| 
 | |
| 	// Note, we treat string as []byte, not []rune as is often
 | |
| 	// done in Go. (And sep as byte, not rune). This is because
 | |
| 	// most/all supported OS' treat paths as string of non-zero
 | |
| 	// bytes. A filename may be displayed as a sequence of Unicode
 | |
| 	// runes (typically encoded as UTF-8) but paths are
 | |
| 	// not required to be valid UTF-8 or in any normalized form
 | |
| 	// (e.g. "é" (U+00C9) and "é" (U+0065,U+0301) are different
 | |
| 	// file names.
 | |
| 	c := []byte(path.Clean(paths[0]))
 | |
| 
 | |
| 	// We add a trailing sep to handle the case where the
 | |
| 	// common prefix directory is included in the path list
 | |
| 	// (e.g. /home/user1, /home/user1/foo, /home/user1/bar).
 | |
| 	// path.Clean will have cleaned off trailing / separators with
 | |
| 	// the exception of the root directory, "/" (in which case we
 | |
| 	// make it "//", but this will get fixed up to "/" below).
 | |
| 	c = append(c, sep)
 | |
| 
 | |
| 	// Ignore the first path since it's already in c
 | |
| 	for _, v := range paths[1:] {
 | |
| 		// Clean up each path before testing it
 | |
| 		v = path.Clean(v) + string(sep)
 | |
| 
 | |
| 		// Find the first non-common byte and truncate c
 | |
| 		if len(v) < len(c) {
 | |
| 			c = c[:len(v)]
 | |
| 		}
 | |
| 		for i := 0; i < len(c); i++ {
 | |
| 			if v[i] != c[i] {
 | |
| 				c = c[:i]
 | |
| 				break
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Remove trailing non-separator characters and the final separator
 | |
| 	for i := len(c) - 1; i >= 0; i-- {
 | |
| 		if c[i] == sep {
 | |
| 			c = c[:i]
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return string(c)
 | |
| }
 | 
![github-action[bot]](/assets/img/avatar_default.png)