func IsDir(name string) (bool, error) {
	fi, err := os.Stat(name)
	if err != nil {
		return false, err
	}
	if !fi.IsDir() {
		return false, fmt.Errorf("%q is not a directory", name)
	}
	return true, nil
}
IsDir determines is the path given is a directory or not.
package fs
import (
	"errors"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"runtime"
	"syscall"
)
func RenameWithFallback(src, dst string) error {
	_, err := os.Stat(src)
	if err != nil {
		return fmt.Errorf("cannot stat %s: %w", src, err)
	}
	err = os.Rename(src, dst)
	if err == nil {
		return nil
	}
	return renameFallback(err, src, dst)
}
func renameByCopy(src, dst string) error {
	var cerr error
	if dir, _ := IsDir(src); dir {
		cerr = CopyDir(src, dst)
		if cerr != nil {
			cerr = fmt.Errorf("copying directory failed: %w", cerr)
		}
	} else {
		cerr = copyFile(src, dst)
		if cerr != nil {
			cerr = fmt.Errorf("copying file failed: %w", cerr)
		}
	}
	if cerr != nil {
		return fmt.Errorf("rename fallback failed: cannot rename %s to %s: %w", src, dst, cerr)
	}
	if err := os.RemoveAll(src); err != nil {
		return fmt.Errorf("cannot delete %s: %w", src, err)
	}
	return nil
}
var (
	errSrcNotDir = errors.New("source is not a directory")
	errDstExist  = errors.New("destination already exists")
)
func CopyDir(src, dst string) error {
	src = filepath.Clean(src)
	dst = filepath.Clean(dst)
	fi, err := os.Lstat(src)
	if err != nil {
		return err
	}
	if !fi.IsDir() {
		return errSrcNotDir
	}
	_, err = os.Stat(dst)
	if err != nil && !os.IsNotExist(err) {
		return err
	}
	if err == nil {
		return errDstExist
	}
	if err = os.MkdirAll(dst, fi.Mode()); err != nil {
		return fmt.Errorf("cannot mkdir %s: %w", dst, err)
	}
	entries, err := os.ReadDir(src)
	if err != nil {
		return fmt.Errorf("cannot read directory %s: %w", dst, err)
	}
	for _, entry := range entries {
		srcPath := filepath.Join(src, entry.Name())
		dstPath := filepath.Join(dst, entry.Name())
		if entry.IsDir() {
			if err = CopyDir(srcPath, dstPath); err != nil {
				return fmt.Errorf("copying directory failed: %w", err)
			}
		} else {
			if err = copyFile(srcPath, dstPath); err != nil {
				return fmt.Errorf("copying file failed: %w", err)
			}
		}
	}
	return nil
}
func copyFile(src, dst string) (err error) {
	if sym, err := IsSymlink(src); err != nil {
		return fmt.Errorf("symlink check failed: %w", err)
	} else if sym {
		if err := cloneSymlink(src, dst); err != nil {
			if runtime.GOOS == "windows" {
				if lerr, ok := err.(*os.LinkError); ok && lerr.Err != syscall.Errno(1314) {
					return err
				}
			} else {
				return err
			}
		} else {
			return nil
		}
	}
	in, err := os.Open(src)
	if err != nil {
		return
	}
	defer in.Close()
	out, err := os.Create(dst)
	if err != nil {
		return
	}
	if _, err = io.Copy(out, in); err != nil {
		out.Close()
		return
	}
	if err = out.Close(); err != nil {
		return
	}
	si, err := os.Stat(src)
	if err != nil {
		return
	}
	if runtime.GOOS == "windows" {
		dst = fixLongPath(dst)
	}
	err = os.Chmod(dst, si.Mode())
	return
}
func cloneSymlink(sl, dst string) error {
	resolved, err := os.Readlink(sl)
	if err != nil {
		return err
	}
	return os.Symlink(resolved, dst)
}