github.com/xhghs/rclone@v1.51.1-0.20200430155106-e186a28cced8/cmd/lsf/lsf.go (about)

     1  package lsf
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  
     9  	"github.com/pkg/errors"
    10  	"github.com/rclone/rclone/cmd"
    11  	"github.com/rclone/rclone/cmd/ls/lshelp"
    12  	"github.com/rclone/rclone/fs"
    13  	"github.com/rclone/rclone/fs/config/flags"
    14  	"github.com/rclone/rclone/fs/hash"
    15  	"github.com/rclone/rclone/fs/operations"
    16  	"github.com/spf13/cobra"
    17  )
    18  
    19  var (
    20  	format    string
    21  	separator string
    22  	dirSlash  bool
    23  	recurse   bool
    24  	hashType  = hash.MD5
    25  	filesOnly bool
    26  	dirsOnly  bool
    27  	csv       bool
    28  	absolute  bool
    29  )
    30  
    31  func init() {
    32  	cmd.Root.AddCommand(commandDefinition)
    33  	cmdFlags := commandDefinition.Flags()
    34  	flags.StringVarP(cmdFlags, &format, "format", "F", "p", "Output format - see  help for details")
    35  	flags.StringVarP(cmdFlags, &separator, "separator", "s", ";", "Separator for the items in the format.")
    36  	flags.BoolVarP(cmdFlags, &dirSlash, "dir-slash", "d", true, "Append a slash to directory names.")
    37  	flags.FVarP(cmdFlags, &hashType, "hash", "", "Use this hash when `h` is used in the format MD5|SHA-1|DropboxHash")
    38  	flags.BoolVarP(cmdFlags, &filesOnly, "files-only", "", false, "Only list files.")
    39  	flags.BoolVarP(cmdFlags, &dirsOnly, "dirs-only", "", false, "Only list directories.")
    40  	flags.BoolVarP(cmdFlags, &csv, "csv", "", false, "Output in CSV format.")
    41  	flags.BoolVarP(cmdFlags, &absolute, "absolute", "", false, "Put a leading / in front of path names.")
    42  	flags.BoolVarP(cmdFlags, &recurse, "recursive", "R", false, "Recurse into the listing.")
    43  }
    44  
    45  var commandDefinition = &cobra.Command{
    46  	Use:   "lsf remote:path",
    47  	Short: `List directories and objects in remote:path formatted for parsing`,
    48  	Long: `
    49  List the contents of the source path (directories and objects) to
    50  standard output in a form which is easy to parse by scripts.  By
    51  default this will just be the names of the objects and directories,
    52  one per line.  The directories will have a / suffix.
    53  
    54  Eg
    55  
    56      $ rclone lsf swift:bucket
    57      bevajer5jef
    58      canole
    59      diwogej7
    60      ferejej3gux/
    61      fubuwic
    62  
    63  Use the --format option to control what gets listed.  By default this
    64  is just the path, but you can use these parameters to control the
    65  output:
    66  
    67      p - path
    68      s - size
    69      t - modification time
    70      h - hash
    71      i - ID of object
    72      o - Original ID of underlying object
    73      m - MimeType of object if known
    74      e - encrypted name
    75      T - tier of storage if known, eg "Hot" or "Cool"
    76  
    77  So if you wanted the path, size and modification time, you would use
    78  --format "pst", or maybe --format "tsp" to put the path last.
    79  
    80  Eg
    81  
    82      $ rclone lsf  --format "tsp" swift:bucket
    83      2016-06-25 18:55:41;60295;bevajer5jef
    84      2016-06-25 18:55:43;90613;canole
    85      2016-06-25 18:55:43;94467;diwogej7
    86      2018-04-26 08:50:45;0;ferejej3gux/
    87      2016-06-25 18:55:40;37600;fubuwic
    88  
    89  If you specify "h" in the format you will get the MD5 hash by default,
    90  use the "--hash" flag to change which hash you want.  Note that this
    91  can be returned as an empty string if it isn't available on the object
    92  (and for directories), "ERROR" if there was an error reading it from
    93  the object and "UNSUPPORTED" if that object does not support that hash
    94  type.
    95  
    96  For example to emulate the md5sum command you can use
    97  
    98      rclone lsf -R --hash MD5 --format hp --separator "  " --files-only .
    99  
   100  Eg
   101  
   102      $ rclone lsf -R --hash MD5 --format hp --separator "  " --files-only swift:bucket 
   103      7908e352297f0f530b84a756f188baa3  bevajer5jef
   104      cd65ac234e6fea5925974a51cdd865cc  canole
   105      03b5341b4f234b9d984d03ad076bae91  diwogej7
   106      8fd37c3810dd660778137ac3a66cc06d  fubuwic
   107      99713e14a4c4ff553acaf1930fad985b  gixacuh7ku
   108  
   109  (Though "rclone md5sum ." is an easier way of typing this.)
   110  
   111  By default the separator is ";" this can be changed with the
   112  --separator flag.  Note that separators aren't escaped in the path so
   113  putting it last is a good strategy.
   114  
   115  Eg
   116  
   117      $ rclone lsf  --separator "," --format "tshp" swift:bucket
   118      2016-06-25 18:55:41,60295,7908e352297f0f530b84a756f188baa3,bevajer5jef
   119      2016-06-25 18:55:43,90613,cd65ac234e6fea5925974a51cdd865cc,canole
   120      2016-06-25 18:55:43,94467,03b5341b4f234b9d984d03ad076bae91,diwogej7
   121      2018-04-26 08:52:53,0,,ferejej3gux/
   122      2016-06-25 18:55:40,37600,8fd37c3810dd660778137ac3a66cc06d,fubuwic
   123  
   124  You can output in CSV standard format.  This will escape things in "
   125  if they contain ,
   126  
   127  Eg
   128  
   129      $ rclone lsf --csv --files-only --format ps remote:path
   130      test.log,22355
   131      test.sh,449
   132      "this file contains a comma, in the file name.txt",6
   133  
   134  Note that the --absolute parameter is useful for making lists of files
   135  to pass to an rclone copy with the --files-from flag.
   136  
   137  For example to find all the files modified within one day and copy
   138  those only (without traversing the whole directory structure):
   139  
   140      rclone lsf --absolute --files-only --max-age 1d /path/to/local > new_files
   141      rclone copy --files-from new_files /path/to/local remote:path
   142  
   143  ` + lshelp.Help,
   144  	Run: func(command *cobra.Command, args []string) {
   145  		cmd.CheckArgs(1, 1, command, args)
   146  		fsrc := cmd.NewFsSrc(args)
   147  		cmd.Run(false, false, command, func() error {
   148  			// Work out if the separatorFlag was supplied or not
   149  			separatorFlag := command.Flags().Lookup("separator")
   150  			separatorFlagSupplied := separatorFlag != nil && separatorFlag.Changed
   151  			// Default the separator to , if using CSV
   152  			if csv && !separatorFlagSupplied {
   153  				separator = ","
   154  			}
   155  			return Lsf(context.Background(), fsrc, os.Stdout)
   156  		})
   157  	},
   158  }
   159  
   160  // Lsf lists all the objects in the path with modification time, size
   161  // and path in specific format.
   162  func Lsf(ctx context.Context, fsrc fs.Fs, out io.Writer) error {
   163  	var list operations.ListFormat
   164  	list.SetSeparator(separator)
   165  	list.SetCSV(csv)
   166  	list.SetDirSlash(dirSlash)
   167  	list.SetAbsolute(absolute)
   168  	var opt = operations.ListJSONOpt{
   169  		NoModTime:  true,
   170  		NoMimeType: true,
   171  		DirsOnly:   dirsOnly,
   172  		FilesOnly:  filesOnly,
   173  		Recurse:    recurse,
   174  	}
   175  
   176  	for _, char := range format {
   177  		switch char {
   178  		case 'p':
   179  			list.AddPath()
   180  		case 't':
   181  			list.AddModTime()
   182  			opt.NoModTime = false
   183  		case 's':
   184  			list.AddSize()
   185  		case 'h':
   186  			list.AddHash(hashType)
   187  			opt.ShowHash = true
   188  		case 'i':
   189  			list.AddID()
   190  		case 'm':
   191  			list.AddMimeType()
   192  			opt.NoMimeType = false
   193  		case 'e':
   194  			list.AddEncrypted()
   195  			opt.ShowEncrypted = true
   196  		case 'o':
   197  			list.AddOrigID()
   198  			opt.ShowOrigIDs = true
   199  		case 'T':
   200  			list.AddTier()
   201  		default:
   202  			return errors.Errorf("Unknown format character %q", char)
   203  		}
   204  	}
   205  
   206  	return operations.ListJSON(ctx, fsrc, "", &opt, func(item *operations.ListJSONItem) error {
   207  		_, _ = fmt.Fprintln(out, list.Format(item))
   208  		return nil
   209  	})
   210  }