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.

141 lines
3.1 KiB

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