mirror of
https://github.com/tickstep/aliyunpan.git
synced 2025-01-23 14:32:14 +08:00
add symlink file util function
This commit is contained in:
parent
b3a7a375d0
commit
797239361c
@ -15,6 +15,7 @@ package pandownload
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/tickstep/aliyunpan-api/aliyunpan"
|
"github.com/tickstep/aliyunpan-api/aliyunpan"
|
||||||
|
"github.com/tickstep/aliyunpan/internal/localfile"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -26,7 +27,8 @@ func CheckFileValid(filePath string, fileInfo *aliyunpan.FileEntity) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileExist 检查文件是否存在,
|
// FileExist 检查文件是否存在
|
||||||
|
//
|
||||||
// 只有当文件存在, 文件大小不为0或断点续传文件不存在时, 才判断为存在
|
// 只有当文件存在, 文件大小不为0或断点续传文件不存在时, 才判断为存在
|
||||||
func FileExist(path string) bool {
|
func FileExist(path string) bool {
|
||||||
if info, err := os.Stat(path); err == nil {
|
if info, err := os.Stat(path); err == nil {
|
||||||
@ -40,3 +42,23 @@ func FileExist(path string) bool {
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SymlinkFileExist 检查文件是否存在
|
||||||
|
//
|
||||||
|
// 逻辑和 FileExist 一致,增加符号链接文件的支持
|
||||||
|
func SymlinkFileExist(fullPath, rootPath string) bool {
|
||||||
|
originSaveRootSymlinkFile := localfile.NewSymlinkFile(rootPath)
|
||||||
|
suffixPath := localfile.GetSuffixPath(fullPath, rootPath)
|
||||||
|
savePathSymlinkFile, savePathFileInfo, err := localfile.RetrieveRealPathFromLogicSuffixPath(originSaveRootSymlinkFile, suffixPath)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
if savePathFileInfo.Size() == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if _, err = os.Stat(savePathSymlinkFile.RealPath + DownloadSuffix); err != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
@ -25,10 +25,7 @@ func (s *SymlinkFile) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewSymlinkFile(filePath string) SymlinkFile {
|
func NewSymlinkFile(filePath string) SymlinkFile {
|
||||||
p := path.Clean(strings.ReplaceAll(filePath, "\\", "/"))
|
p := CleanPath(filePath)
|
||||||
if p == "." {
|
|
||||||
p = ""
|
|
||||||
}
|
|
||||||
return SymlinkFile{
|
return SymlinkFile{
|
||||||
LogicPath: p,
|
LogicPath: p,
|
||||||
RealPath: p,
|
RealPath: p,
|
||||||
@ -37,6 +34,26 @@ func NewSymlinkFile(filePath string) SymlinkFile {
|
|||||||
|
|
||||||
type MyWalkFunc func(path SymlinkFile, info fs.FileInfo, err error) error
|
type MyWalkFunc func(path SymlinkFile, info fs.FileInfo, err error) error
|
||||||
|
|
||||||
|
// CleanPath 规范化文件路径,分隔符全部转换成Unix文件分隔符"/"。同时清除后缀无用的"/"路径
|
||||||
|
func CleanPath(p string) string {
|
||||||
|
if p == "" || p == "/" {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
p = path.Clean(strings.ReplaceAll(p, "\\", "/"))
|
||||||
|
if p == "." {
|
||||||
|
p = ""
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSuffixPath 获取相对路径。即fullFilePath相对rootFilePath的相对路径
|
||||||
|
func GetSuffixPath(fullFilePath, rootFilePath string) string {
|
||||||
|
rootFilePath = CleanPath(rootFilePath)
|
||||||
|
fullFilePath = CleanPath(fullFilePath)
|
||||||
|
return strings.TrimPrefix(strings.TrimPrefix(fullFilePath, rootFilePath), "/")
|
||||||
|
}
|
||||||
|
|
||||||
// RetrieveRealPath 递归调用找到软链接文件的真实文件对应的路径信息
|
// RetrieveRealPath 递归调用找到软链接文件的真实文件对应的路径信息
|
||||||
func RetrieveRealPath(file SymlinkFile) (SymlinkFile, os.FileInfo, error) {
|
func RetrieveRealPath(file SymlinkFile) (SymlinkFile, os.FileInfo, error) {
|
||||||
info, err := os.Lstat(file.RealPath)
|
info, err := os.Lstat(file.RealPath)
|
||||||
@ -62,11 +79,7 @@ func RetrieveRealPath(file SymlinkFile) (SymlinkFile, os.FileInfo, error) {
|
|||||||
//
|
//
|
||||||
// 如果/Volumes/Downloads存在而后面部分不存在,则最终结果返回/Volumes/Downloads对应的文件信息,同时返回error
|
// 如果/Volumes/Downloads存在而后面部分不存在,则最终结果返回/Volumes/Downloads对应的文件信息,同时返回error
|
||||||
func RetrieveRealPathFromLogicPath(logicFilePath string) (SymlinkFile, os.FileInfo, error) {
|
func RetrieveRealPathFromLogicPath(logicFilePath string) (SymlinkFile, os.FileInfo, error) {
|
||||||
logicFilePath = strings.ReplaceAll(logicFilePath, "\\", "/")
|
logicFilePath = CleanPath(logicFilePath)
|
||||||
logicFilePath = path.Clean(logicFilePath)
|
|
||||||
if logicFilePath == "." {
|
|
||||||
logicFilePath = ""
|
|
||||||
}
|
|
||||||
if logicFilePath == "/" {
|
if logicFilePath == "/" {
|
||||||
return RetrieveRealPath(NewSymlinkFile(logicFilePath))
|
return RetrieveRealPath(NewSymlinkFile(logicFilePath))
|
||||||
}
|
}
|
||||||
@ -101,6 +114,45 @@ func RetrieveRealPathFromLogicPath(logicFilePath string) (SymlinkFile, os.FileIn
|
|||||||
return exitedSymlinkFile, exitedFileInfo, nil
|
return exitedSymlinkFile, exitedFileInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RetrieveRealPathFromLogicSuffixPath 通过指定根目录和后缀逻辑路径,获取文件对应的真实路径信息
|
||||||
|
//
|
||||||
|
// 整体功能和 RetrieveRealPathFromLogicPath 一致,将逻辑路径分成根路径和后缀路径两部分,并且根路径必须存在。
|
||||||
|
func RetrieveRealPathFromLogicSuffixPath(rootFile SymlinkFile, logicSuffixPath string) (SymlinkFile, os.FileInfo, error) {
|
||||||
|
if rootFile.LogicPath == "" || rootFile.RealPath == "" {
|
||||||
|
return rootFile, nil, fmt.Errorf("root file path error")
|
||||||
|
}
|
||||||
|
rootFile.LogicPath = CleanPath(rootFile.LogicPath)
|
||||||
|
rootFile.RealPath = CleanPath(rootFile.RealPath)
|
||||||
|
rootFileInfo, e := os.Lstat(rootFile.RealPath)
|
||||||
|
if e != nil {
|
||||||
|
return rootFile, nil, e
|
||||||
|
}
|
||||||
|
|
||||||
|
logicSuffixPath = CleanPath(logicSuffixPath)
|
||||||
|
pathParts := strings.Split(logicSuffixPath, "/")
|
||||||
|
exitedSymlinkFile := rootFile
|
||||||
|
exitedFileInfo := rootFileInfo
|
||||||
|
|
||||||
|
sf := rootFile
|
||||||
|
var fi os.FileInfo
|
||||||
|
var err error
|
||||||
|
for _, p := range pathParts {
|
||||||
|
if p == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
sf.LogicPath += "/" + p
|
||||||
|
sf.RealPath += "/" + p
|
||||||
|
sf, fi, err = RetrieveRealPath(sf)
|
||||||
|
if err != nil {
|
||||||
|
// may be permission deny or not existed
|
||||||
|
return exitedSymlinkFile, exitedFileInfo, err
|
||||||
|
}
|
||||||
|
exitedSymlinkFile = sf
|
||||||
|
exitedFileInfo = fi
|
||||||
|
}
|
||||||
|
return exitedSymlinkFile, exitedFileInfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
// WalkAllFile 遍历本地文件,支持软链接(符号逻辑)文件(Linux & Windows & macOS)
|
// WalkAllFile 遍历本地文件,支持软链接(符号逻辑)文件(Linux & Windows & macOS)
|
||||||
func WalkAllFile(file SymlinkFile, walkFn MyWalkFunc) error {
|
func WalkAllFile(file SymlinkFile, walkFn MyWalkFunc) error {
|
||||||
file.LogicPath = path.Clean(strings.ReplaceAll(file.LogicPath, "\\", "/"))
|
file.LogicPath = path.Clean(strings.ReplaceAll(file.LogicPath, "\\", "/"))
|
||||||
|
@ -50,3 +50,14 @@ func TestRetrieveRealPathFromLogicPath(t *testing.T) {
|
|||||||
}
|
}
|
||||||
fmt.Println(sf)
|
fmt.Println(sf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRetrieveRealPathFromLogicSuffixPath(t *testing.T) {
|
||||||
|
rootPath := NewSymlinkFile("/Volumes/Downloads/dev/测试同步盘/new_lks")
|
||||||
|
rootPath, _, _ = RetrieveRealPath(rootPath)
|
||||||
|
suffixPath := "test/未命名文件夹cmd/sync_drive_config.json"
|
||||||
|
sf, _, e := RetrieveRealPathFromLogicSuffixPath(rootPath, suffixPath)
|
||||||
|
if e != nil {
|
||||||
|
fmt.Println(e)
|
||||||
|
}
|
||||||
|
fmt.Println(sf)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user