github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/cmd/size/size.go (about) 1 // Package size provides the size command. 2 package size 3 4 import ( 5 "context" 6 "encoding/json" 7 "fmt" 8 "os" 9 "strconv" 10 11 "github.com/rclone/rclone/cmd" 12 "github.com/rclone/rclone/fs" 13 "github.com/rclone/rclone/fs/config/flags" 14 "github.com/rclone/rclone/fs/operations" 15 "github.com/spf13/cobra" 16 ) 17 18 var jsonOutput bool 19 20 func init() { 21 cmd.Root.AddCommand(commandDefinition) 22 cmdFlags := commandDefinition.Flags() 23 flags.BoolVarP(cmdFlags, &jsonOutput, "json", "", false, "Format output as JSON", "") 24 } 25 26 var commandDefinition = &cobra.Command{ 27 Use: "size remote:path", 28 Short: `Prints the total size and number of objects in remote:path.`, 29 Long: ` 30 Counts objects in the path and calculates the total size. Prints the 31 result to standard output. 32 33 By default the output is in human-readable format, but shows values in 34 both human-readable format as well as the raw numbers (global option 35 ` + "`--human-readable`" + ` is not considered). Use option ` + "`--json`" + ` 36 to format output as JSON instead. 37 38 Recurses by default, use ` + "`--max-depth 1`" + ` to stop the 39 recursion. 40 41 Some backends do not always provide file sizes, see for example 42 [Google Photos](/googlephotos/#size) and 43 [Google Docs](/drive/#limitations-of-google-docs). 44 Rclone will then show a notice in the log indicating how many such 45 files were encountered, and count them in as empty files in the output 46 of the size command. 47 `, 48 Annotations: map[string]string{ 49 "versionIntroduced": "v1.23", 50 "groups": "Filter,Listing", 51 }, 52 Run: func(command *cobra.Command, args []string) { 53 cmd.CheckArgs(1, 1, command, args) 54 fsrc := cmd.NewFsSrc(args) 55 cmd.Run(false, false, command, func() error { 56 var err error 57 var results struct { 58 Count int64 `json:"count"` 59 Bytes int64 `json:"bytes"` 60 Sizeless int64 `json:"sizeless"` 61 } 62 63 results.Count, results.Bytes, results.Sizeless, err = operations.Count(context.Background(), fsrc) 64 if err != nil { 65 return err 66 } 67 if results.Sizeless > 0 { 68 fs.Logf(fsrc, "Size may be underestimated due to %d objects with unknown size", results.Sizeless) 69 } 70 if jsonOutput { 71 return json.NewEncoder(os.Stdout).Encode(results) 72 } 73 count := strconv.FormatInt(results.Count, 10) 74 countSuffix := fs.CountSuffix(results.Count).String() 75 if count == countSuffix { 76 fmt.Printf("Total objects: %s\n", count) 77 } else { 78 fmt.Printf("Total objects: %s (%s)\n", countSuffix, count) 79 } 80 fmt.Printf("Total size: %s (%d Byte)\n", fs.SizeSuffix(results.Bytes).ByteUnit(), results.Bytes) 81 if results.Sizeless > 0 { 82 fmt.Printf("Total objects with unknown size: %s (%d)\n", fs.CountSuffix(results.Sizeless), results.Sizeless) 83 } 84 return nil 85 }) 86 }, 87 }