2022-08-19 17:27:54 +08:00
|
|
|
|
package command
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"github.com/tickstep/aliyunpan-api/aliyunpan"
|
|
|
|
|
"github.com/tickstep/aliyunpan/cmder"
|
|
|
|
|
"github.com/tickstep/aliyunpan/internal/config"
|
|
|
|
|
"github.com/urfave/cli"
|
|
|
|
|
"path"
|
|
|
|
|
"strings"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func CmdTree() cli.Command {
|
|
|
|
|
return cli.Command{
|
|
|
|
|
Name: "tree",
|
|
|
|
|
Usage: "列出目录的树形图",
|
|
|
|
|
UsageText: cmder.App().Name + " tree <目录>",
|
|
|
|
|
Description: `
|
|
|
|
|
列出指定目录内的文件和目录, 并以树形图的方式呈现
|
|
|
|
|
|
|
|
|
|
示例:
|
|
|
|
|
|
|
|
|
|
列出 当前工作目录 内的文件和目录的树形图
|
|
|
|
|
aliyunpan tree
|
|
|
|
|
|
|
|
|
|
列出 /我的资源 内的文件和目录的树形图
|
|
|
|
|
aliyunpan tree /我的资源
|
|
|
|
|
|
2022-08-31 11:06:57 +08:00
|
|
|
|
列出 /我的资源 内的文件和目录的树形图,并且显示文件对应的完整绝对路径
|
|
|
|
|
aliyunpan tree -fp /我的资源
|
2022-08-19 17:27:54 +08:00
|
|
|
|
`,
|
|
|
|
|
Category: "阿里云盘",
|
|
|
|
|
Before: cmder.ReloadConfigFunc,
|
|
|
|
|
Action: func(c *cli.Context) error {
|
|
|
|
|
if config.Config.ActiveUser() == nil {
|
|
|
|
|
fmt.Println("未登录账号")
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2022-08-31 11:06:57 +08:00
|
|
|
|
RunTree(parseDriveId(c), c.Args().Get(0), c.Bool("fp"))
|
2022-08-19 17:27:54 +08:00
|
|
|
|
return nil
|
|
|
|
|
},
|
|
|
|
|
Flags: []cli.Flag{
|
|
|
|
|
cli.StringFlag{
|
|
|
|
|
Name: "driveId",
|
|
|
|
|
Usage: "网盘ID",
|
|
|
|
|
Value: "",
|
|
|
|
|
},
|
2022-08-31 11:06:57 +08:00
|
|
|
|
cli.BoolFlag{
|
|
|
|
|
Name: "fp",
|
|
|
|
|
Usage: "full path, 树形图是否显示文件完整路径",
|
|
|
|
|
},
|
2022-08-19 17:27:54 +08:00
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
indentPrefix = "│ "
|
|
|
|
|
pathPrefix = "├──"
|
|
|
|
|
lastFilePrefix = "└──"
|
|
|
|
|
)
|
|
|
|
|
|
2022-08-31 10:36:33 +08:00
|
|
|
|
type (
|
|
|
|
|
treeStatistic struct {
|
|
|
|
|
CountOfDir int64
|
|
|
|
|
CountOfFile int64
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
2022-08-31 11:06:57 +08:00
|
|
|
|
func getTree(driveId, pathStr string, depth int, statistic *treeStatistic, showFullPath bool) {
|
2022-08-19 17:27:54 +08:00
|
|
|
|
activeUser := config.Config.ActiveUser()
|
|
|
|
|
pathStr = activeUser.PathJoin(driveId, pathStr)
|
|
|
|
|
pathStr = path.Clean(pathStr)
|
|
|
|
|
|
|
|
|
|
targetPathInfo, err1 := activeUser.PanClient().FileInfoByPath(driveId, pathStr)
|
|
|
|
|
if err1 != nil {
|
|
|
|
|
fmt.Println(err1)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
fileList := aliyunpan.FileList{}
|
|
|
|
|
fileListParam := &aliyunpan.FileListParam{}
|
|
|
|
|
fileListParam.ParentFileId = targetPathInfo.FileId
|
|
|
|
|
fileListParam.DriveId = driveId
|
|
|
|
|
fileListParam.OrderBy = aliyunpan.FileOrderByName
|
|
|
|
|
fileListParam.OrderDirection = aliyunpan.FileOrderDirectionAsc
|
|
|
|
|
if targetPathInfo.IsFolder() {
|
|
|
|
|
fileResult, err := activeUser.PanClient().FileListGetAll(fileListParam, 0)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println(err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
fileList = append(fileList, fileResult...)
|
|
|
|
|
} else {
|
|
|
|
|
fileList = append(fileList, targetPathInfo)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
prefix = pathPrefix
|
|
|
|
|
fN = len(fileList)
|
|
|
|
|
indentPrefixStr = strings.Repeat(indentPrefix, depth)
|
|
|
|
|
)
|
|
|
|
|
for i, file := range fileList {
|
|
|
|
|
if file.IsFolder() {
|
2022-08-31 10:36:33 +08:00
|
|
|
|
statistic.CountOfDir += 1
|
2022-08-31 11:06:57 +08:00
|
|
|
|
if showFullPath {
|
|
|
|
|
fmt.Printf("%v%v %v/ -> %s\n", indentPrefixStr, pathPrefix, file.FileName, pathStr+"/"+file.FileName)
|
|
|
|
|
} else {
|
|
|
|
|
fmt.Printf("%v%v %v/\n", indentPrefixStr, pathPrefix, file.FileName)
|
|
|
|
|
}
|
|
|
|
|
getTree(driveId, pathStr+"/"+file.Path, depth+1, statistic, showFullPath)
|
2022-08-19 17:27:54 +08:00
|
|
|
|
continue
|
|
|
|
|
}
|
2022-08-31 10:36:33 +08:00
|
|
|
|
statistic.CountOfFile += 1
|
2022-08-19 17:27:54 +08:00
|
|
|
|
|
|
|
|
|
if i+1 == fN {
|
|
|
|
|
prefix = lastFilePrefix
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-31 11:06:57 +08:00
|
|
|
|
if showFullPath {
|
|
|
|
|
fmt.Printf("%v%v %v -> %s\n", indentPrefixStr, prefix, file.FileName, pathStr+"/"+file.FileName)
|
|
|
|
|
} else {
|
|
|
|
|
fmt.Printf("%v%v %v\n", indentPrefixStr, prefix, file.FileName)
|
|
|
|
|
}
|
2022-08-19 17:27:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// RunTree 列出树形图
|
2022-08-31 11:06:57 +08:00
|
|
|
|
func RunTree(driveId, pathStr string, showFullPath bool) {
|
2022-08-19 17:27:54 +08:00
|
|
|
|
activeUser := config.Config.ActiveUser()
|
|
|
|
|
activeUser.PanClient().ClearCache()
|
|
|
|
|
activeUser.PanClient().EnableCache()
|
|
|
|
|
defer activeUser.PanClient().DisableCache()
|
|
|
|
|
pathStr = activeUser.PathJoin(driveId, pathStr)
|
2022-08-31 10:36:33 +08:00
|
|
|
|
statistic := &treeStatistic{
|
|
|
|
|
CountOfDir: 0,
|
|
|
|
|
CountOfFile: 0,
|
|
|
|
|
}
|
2022-08-19 17:27:54 +08:00
|
|
|
|
fmt.Printf("%s\n", pathStr)
|
2022-08-31 11:06:57 +08:00
|
|
|
|
getTree(driveId, pathStr, 0, statistic, showFullPath)
|
2022-08-31 10:36:33 +08:00
|
|
|
|
fmt.Printf("\n%d 个文件夹, %d 个文件\n", statistic.CountOfDir, statistic.CountOfFile)
|
2022-08-19 17:27:54 +08:00
|
|
|
|
}
|