You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
3.3 KiB

  1. package shell
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/chrislusf/seaweedfs/weed/filer2"
  6. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  7. "io"
  8. "os"
  9. "os/user"
  10. "strconv"
  11. "strings"
  12. )
  13. func init() {
  14. commands = append(commands, &commandFsLs{})
  15. }
  16. type commandFsLs struct {
  17. }
  18. func (c *commandFsLs) Name() string {
  19. return "fs.ls"
  20. }
  21. func (c *commandFsLs) Help() string {
  22. return `list all files under a directory
  23. fs.ls [-l] [-a] http://<filer_server>:<port>/dir/
  24. fs.ls [-l] [-a] http://<filer_server>:<port>/dir/file_name
  25. fs.ls [-l] [-a] http://<filer_server>:<port>/dir/file_prefix
  26. `
  27. }
  28. func (c *commandFsLs) Do(args []string, commandEnv *commandEnv, writer io.Writer) (err error) {
  29. var isLongFormat, showHidden bool
  30. for _, arg := range args {
  31. switch arg {
  32. case "-a":
  33. showHidden = true
  34. case "-l":
  35. isLongFormat = true
  36. }
  37. }
  38. input := ""
  39. if len(args) > 0 {
  40. input = args[len(args)-1]
  41. if strings.HasPrefix(input, "-") {
  42. input = ""
  43. }
  44. }
  45. filerServer, filerPort, path, err := commandEnv.parseUrl(input)
  46. if err != nil {
  47. return err
  48. }
  49. if input == "" && !strings.HasSuffix(path, "/") {
  50. path = path + "/"
  51. }
  52. dir, name := filer2.FullPath(path).DirAndName()
  53. // println("path", path, "dir", dir, "name", name)
  54. if strings.HasSuffix(path, "/") {
  55. if path == "/" {
  56. dir, name = "/", ""
  57. } else {
  58. dir, name = path[0 : len(path)-1], ""
  59. }
  60. }
  61. ctx := context.Background()
  62. return commandEnv.withFilerClient(ctx, filerServer, filerPort, func(client filer_pb.SeaweedFilerClient) error {
  63. return paginateOneDirectory(ctx, writer, client, dir, name, 1000, isLongFormat, showHidden)
  64. })
  65. }
  66. func paginateOneDirectory(ctx context.Context, writer io.Writer, client filer_pb.SeaweedFilerClient, dir, name string, paginateSize int, isLongFormat, showHidden bool) (err error) {
  67. entryCount := 0
  68. paginatedCount := -1
  69. startFromFileName := ""
  70. for paginatedCount == -1 || paginatedCount == paginateSize {
  71. resp, listErr := client.ListEntries(ctx, &filer_pb.ListEntriesRequest{
  72. Directory: dir,
  73. Prefix: name,
  74. StartFromFileName: startFromFileName,
  75. InclusiveStartFrom: false,
  76. Limit: uint32(paginateSize),
  77. })
  78. if listErr != nil {
  79. err = listErr
  80. return
  81. }
  82. paginatedCount = len(resp.Entries)
  83. for _, entry := range resp.Entries {
  84. if !showHidden && strings.HasPrefix(entry.Name, ".") {
  85. continue
  86. }
  87. entryCount++
  88. if isLongFormat {
  89. fileMode := os.FileMode(entry.Attributes.FileMode)
  90. userName, groupNames := entry.Attributes.UserName, entry.Attributes.GroupName
  91. if userName == "" {
  92. if user, userErr := user.LookupId(strconv.Itoa(int(entry.Attributes.Uid))); userErr == nil {
  93. userName = user.Username
  94. }
  95. }
  96. groupName := ""
  97. if len(groupNames) > 0 {
  98. groupName = groupNames[0]
  99. }
  100. if groupName == "" {
  101. if group, groupErr := user.LookupGroupId(strconv.Itoa(int(entry.Attributes.Gid))); groupErr == nil {
  102. groupName = group.Name
  103. }
  104. }
  105. if dir == "/" {
  106. // just for printing
  107. dir = ""
  108. }
  109. fmt.Fprintf(writer, "%s %3d %s %s %6d %s/%s\n",
  110. fileMode, len(entry.Chunks),
  111. userName, groupName,
  112. filer2.TotalSize(entry.Chunks), dir, entry.Name)
  113. } else {
  114. fmt.Fprintf(writer, "%s\n", entry.Name)
  115. }
  116. startFromFileName = entry.Name
  117. }
  118. }
  119. if isLongFormat {
  120. fmt.Fprintf(writer, "total %d\n", entryCount)
  121. }
  122. return
  123. }