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.

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