package shell import ( "context" "fmt" "github.com/chrislusf/seaweedfs/weed/filer2" "github.com/chrislusf/seaweedfs/weed/pb/filer_pb" "io" "os" "os/user" "strconv" "strings" ) func init() { commands = append(commands, &commandFsLs{}) } type commandFsLs struct { } func (c *commandFsLs) Name() string { return "fs.ls" } func (c *commandFsLs) Help() string { return `list all files under a directory fs.ls [-l] [-a] /dir/ fs.ls [-l] [-a] /dir/file_name fs.ls [-l] [-a] /dir/file_prefix fs.ls [-l] [-a] http://:/dir/ fs.ls [-l] [-a] http://:/dir/file_name fs.ls [-l] [-a] http://:/dir/file_prefix ` } func (c *commandFsLs) Do(args []string, commandEnv *commandEnv, writer io.Writer) (err error) { var isLongFormat, showHidden bool for _, arg := range args { if !strings.HasPrefix(arg, "-") { break } for _, t := range arg { switch t { case 'a': showHidden = true case 'l': isLongFormat = true } } } input := findInputDirectory(args) filerServer, filerPort, path, err := commandEnv.parseUrl(input) if err != nil { return err } ctx := context.Background() if commandEnv.isDirectory(ctx, filerServer, filerPort, path) { path = path + "/" } dir, name := filer2.FullPath(path).DirAndName() return commandEnv.withFilerClient(ctx, filerServer, filerPort, func(client filer_pb.SeaweedFilerClient) error { return paginateOneDirectory(ctx, writer, client, dir, name, 1000, isLongFormat, showHidden) }) } func paginateOneDirectory(ctx context.Context, writer io.Writer, client filer_pb.SeaweedFilerClient, dir, name string, paginateSize int, isLongFormat, showHidden bool) (err error) { entryCount := 0 paginatedCount := -1 startFromFileName := "" for paginatedCount == -1 || paginatedCount == paginateSize { resp, listErr := client.ListEntries(ctx, &filer_pb.ListEntriesRequest{ Directory: dir, Prefix: name, StartFromFileName: startFromFileName, InclusiveStartFrom: false, Limit: uint32(paginateSize), }) if listErr != nil { err = listErr return } paginatedCount = len(resp.Entries) for _, entry := range resp.Entries { if !showHidden && strings.HasPrefix(entry.Name, ".") { continue } entryCount++ if isLongFormat { fileMode := os.FileMode(entry.Attributes.FileMode) userName, groupNames := entry.Attributes.UserName, entry.Attributes.GroupName if userName == "" { if user, userErr := user.LookupId(strconv.Itoa(int(entry.Attributes.Uid))); userErr == nil { userName = user.Username } } groupName := "" if len(groupNames) > 0 { groupName = groupNames[0] } if groupName == "" { if group, groupErr := user.LookupGroupId(strconv.Itoa(int(entry.Attributes.Gid))); groupErr == nil { groupName = group.Name } } if dir == "/" { // just for printing dir = "" } fmt.Fprintf(writer, "%s %3d %s %s %6d %s/%s\n", fileMode, len(entry.Chunks), userName, groupName, filer2.TotalSize(entry.Chunks), dir, entry.Name) } else { fmt.Fprintf(writer, "%s\n", entry.Name) } startFromFileName = entry.Name } } if isLongFormat { fmt.Fprintf(writer, "total %d\n", entryCount) } return }