github.com/advanderveer/restic@v0.8.1-0.20171209104529-42a8c19aaea6/cmd/restic/cmd_ls.go (about) 1 package main 2 3 import ( 4 "context" 5 "path/filepath" 6 7 "github.com/spf13/cobra" 8 9 "github.com/restic/restic/internal/errors" 10 "github.com/restic/restic/internal/repository" 11 "github.com/restic/restic/internal/restic" 12 ) 13 14 var cmdLs = &cobra.Command{ 15 Use: "ls [flags] [snapshot-ID ...]", 16 Short: "List files in a snapshot", 17 Long: ` 18 The "ls" command allows listing files and directories in a snapshot. 19 20 The special snapshot-ID "latest" can be used to list files and directories of the latest snapshot in the repository. 21 `, 22 DisableAutoGenTag: true, 23 RunE: func(cmd *cobra.Command, args []string) error { 24 return runLs(lsOptions, globalOptions, args) 25 }, 26 } 27 28 // LsOptions collects all options for the ls command. 29 type LsOptions struct { 30 ListLong bool 31 Host string 32 Tags restic.TagLists 33 Paths []string 34 } 35 36 var lsOptions LsOptions 37 38 func init() { 39 cmdRoot.AddCommand(cmdLs) 40 41 flags := cmdLs.Flags() 42 flags.BoolVarP(&lsOptions.ListLong, "long", "l", false, "use a long listing format showing size and mode") 43 44 flags.StringVarP(&lsOptions.Host, "host", "H", "", "only consider snapshots for this `host`, when no snapshot ID is given") 45 flags.Var(&lsOptions.Tags, "tag", "only consider snapshots which include this `taglist`, when no snapshot ID is given") 46 flags.StringArrayVar(&lsOptions.Paths, "path", nil, "only consider snapshots which include this (absolute) `path`, when no snapshot ID is given") 47 } 48 49 func printTree(ctx context.Context, repo *repository.Repository, id *restic.ID, prefix string) error { 50 tree, err := repo.LoadTree(ctx, *id) 51 if err != nil { 52 return err 53 } 54 55 for _, entry := range tree.Nodes { 56 Printf("%s\n", formatNode(prefix, entry, lsOptions.ListLong)) 57 58 if entry.Type == "dir" && entry.Subtree != nil { 59 if err = printTree(ctx, repo, entry.Subtree, filepath.Join(prefix, entry.Name)); err != nil { 60 return err 61 } 62 } 63 } 64 65 return nil 66 } 67 68 func runLs(opts LsOptions, gopts GlobalOptions, args []string) error { 69 if len(args) == 0 && opts.Host == "" && len(opts.Tags) == 0 && len(opts.Paths) == 0 { 70 return errors.Fatal("Invalid arguments, either give one or more snapshot IDs or set filters.") 71 } 72 73 repo, err := OpenRepository(gopts) 74 if err != nil { 75 return err 76 } 77 78 if err = repo.LoadIndex(gopts.ctx); err != nil { 79 return err 80 } 81 82 ctx, cancel := context.WithCancel(gopts.ctx) 83 defer cancel() 84 for sn := range FindFilteredSnapshots(ctx, repo, opts.Host, opts.Tags, opts.Paths, args) { 85 Verbosef("snapshot %s of %v at %s):\n", sn.ID().Str(), sn.Paths, sn.Time) 86 87 if err = printTree(gopts.ctx, repo, sn.Tree, string(filepath.Separator)); err != nil { 88 return err 89 } 90 } 91 return nil 92 }