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.

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