2022-08-28 13:21:57 +02:00
// Package lsf provides the lsf command.
2018-01-06 15:39:31 +01:00
package lsf
import (
2019-06-17 10:34:30 +02:00
"context"
2018-01-06 15:39:31 +01:00
"fmt"
"io"
"os"
2019-07-28 19:47:38 +02:00
"github.com/rclone/rclone/cmd"
"github.com/rclone/rclone/cmd/ls/lshelp"
"github.com/rclone/rclone/fs"
2019-10-11 17:55:04 +02:00
"github.com/rclone/rclone/fs/config/flags"
2019-07-28 19:47:38 +02:00
"github.com/rclone/rclone/fs/hash"
"github.com/rclone/rclone/fs/operations"
2018-01-06 15:39:31 +01:00
"github.com/spf13/cobra"
)
var (
2023-12-08 01:29:55 +01:00
format string
timeFormat string
separator string
dirSlash bool
recurse bool
hashType = hash . MD5
filesOnly bool
dirsOnly bool
csv bool
absolute bool
2018-01-06 15:39:31 +01:00
)
func init ( ) {
2019-10-11 17:58:11 +02:00
cmd . Root . AddCommand ( commandDefinition )
2019-10-11 17:55:04 +02:00
cmdFlags := commandDefinition . Flags ( )
2023-07-10 19:34:10 +02:00
flags . StringVarP ( cmdFlags , & format , "format" , "F" , "p" , "Output format - see help for details" , "" )
2023-12-08 01:29:55 +01:00
flags . StringVarP ( cmdFlags , & timeFormat , "time-format" , "t" , "" , "Specify a custom time format, or 'max' for max precision supported by remote (default: 2006-01-02 15:04:05)" , "" )
2023-07-10 19:34:10 +02:00
flags . StringVarP ( cmdFlags , & separator , "separator" , "s" , ";" , "Separator for the items in the format" , "" )
flags . BoolVarP ( cmdFlags , & dirSlash , "dir-slash" , "d" , true , "Append a slash to directory names" , "" )
flags . FVarP ( cmdFlags , & hashType , "hash" , "" , "Use this hash when `h` is used in the format MD5|SHA-1|DropboxHash" , "" )
flags . BoolVarP ( cmdFlags , & filesOnly , "files-only" , "" , false , "Only list files" , "" )
flags . BoolVarP ( cmdFlags , & dirsOnly , "dirs-only" , "" , false , "Only list directories" , "" )
flags . BoolVarP ( cmdFlags , & csv , "csv" , "" , false , "Output in CSV format" , "" )
flags . BoolVarP ( cmdFlags , & absolute , "absolute" , "" , false , "Put a leading / in front of path names" , "" )
flags . BoolVarP ( cmdFlags , & recurse , "recursive" , "R" , false , "Recurse into the listing" , "" )
2018-01-06 15:39:31 +01:00
}
2019-10-11 17:58:11 +02:00
var commandDefinition = & cobra . Command {
2018-01-06 15:39:31 +01:00
Use : "lsf remote:path" ,
2020-09-03 14:12:54 +02:00
Short : ` List directories and objects in remote:path formatted for parsing. ` ,
2018-01-06 18:00:20 +01:00
Long : `
List the contents of the source path ( directories and objects ) to
standard output in a form which is easy to parse by scripts . By
default this will just be the names of the objects and directories ,
one per line . The directories will have a / suffix .
2018-04-25 22:06:42 +02:00
Eg
$ rclone lsf swift : bucket
bevajer5jef
canole
diwogej7
ferejej3gux /
fubuwic
2022-06-19 19:55:37 +02:00
Use the ` + " ` -- format ` " + ` option to control what gets listed . By default this
2018-01-06 18:00:20 +01:00
is just the path , but you can use these parameters to control the
output :
p - path
s - size
t - modification time
2018-01-06 18:53:37 +01:00
h - hash
2019-02-14 09:45:03 +01:00
i - ID of object
o - Original ID of underlying object
2018-05-13 11:37:25 +02:00
m - MimeType of object if known
2019-02-14 09:45:03 +01:00
e - encrypted name
2020-10-13 23:49:58 +02:00
T - tier of storage if known , e . g . "Hot" or "Cool"
2022-05-24 12:31:48 +02:00
M - Metadata of object in JSON blob format , eg { "key" : "value" }
2018-01-06 18:00:20 +01:00
So if you wanted the path , size and modification time , you would use
2022-06-19 19:55:37 +02:00
` + " ` -- format \ "pst\"`, or maybe `--format \"tsp\"`" + ` to put the path last .
2018-01-06 18:00:20 +01:00
2018-04-25 22:06:42 +02:00
Eg
$ rclone lsf -- format "tsp" swift : bucket
2016 - 06 - 25 18 : 55 : 41 ; 60295 ; bevajer5jef
2016 - 06 - 25 18 : 55 : 43 ; 90613 ; canole
2016 - 06 - 25 18 : 55 : 43 ; 94467 ; diwogej7
2018 - 04 - 26 0 8 : 50 : 45 ; 0 ; ferejej3gux /
2016 - 06 - 25 18 : 55 : 40 ; 37600 ; fubuwic
2018-01-06 18:53:37 +01:00
If you specify "h" in the format you will get the MD5 hash by default ,
2022-06-19 19:55:37 +02:00
use the ` + " ` -- hash ` " + ` flag to change which hash you want . Note that this
2018-01-06 18:53:37 +01:00
can be returned as an empty string if it isn ' t available on the object
( and for directories ) , "ERROR" if there was an error reading it from
the object and "UNSUPPORTED" if that object does not support that hash
type .
2021-11-04 12:50:43 +01:00
For example , to emulate the md5sum command you can use
2018-01-06 19:01:29 +01:00
rclone lsf - R -- hash MD5 -- format hp -- separator " " -- files - only .
2018-04-25 22:06:42 +02:00
Eg
2021-11-04 12:50:43 +01:00
$ rclone lsf - R -- hash MD5 -- format hp -- separator " " -- files - only swift : bucket
2018-04-25 22:06:42 +02:00
7908e352297 f0f530b84a756f188baa3 bevajer5jef
cd65ac234e6fea5925974a51cdd865cc canole
03 b5341b4f234b9d984d03ad076bae91 diwogej7
8 fd37c3810dd660778137ac3a66cc06d fubuwic
99713e14 a4c4ff553acaf1930fad985b gixacuh7ku
2018-01-06 19:01:29 +01:00
( Though "rclone md5sum ." is an easier way of typing this . )
2018-01-06 18:00:20 +01:00
By default the separator is ";" this can be changed with the
2022-06-19 19:55:37 +02:00
` + " ` -- separator ` " + ` flag . Note that separators aren ' t escaped in the path so
2018-01-06 18:00:20 +01:00
putting it last is a good strategy .
2018-04-25 22:06:42 +02:00
Eg
$ rclone lsf -- separator "," -- format "tshp" swift : bucket
2016 - 06 - 25 18 : 55 : 41 , 60295 , 7908e352297 f0f530b84a756f188baa3 , bevajer5jef
2016 - 06 - 25 18 : 55 : 43 , 90613 , cd65ac234e6fea5925974a51cdd865cc , canole
2016 - 06 - 25 18 : 55 : 43 , 94467 , 03 b5341b4f234b9d984d03ad076bae91 , diwogej7
2018 - 04 - 26 0 8 : 52 : 53 , 0 , , ferejej3gux /
2016 - 06 - 25 18 : 55 : 40 , 37600 , 8 fd37c3810dd660778137ac3a66cc06d , fubuwic
2018-05-13 13:15:05 +02:00
You can output in CSV standard format . This will escape things in "
if they contain ,
Eg
$ rclone lsf -- csv -- files - only -- format ps remote : path
test . log , 22355
test . sh , 449
"this file contains a comma, in the file name.txt" , 6
2022-06-19 19:55:37 +02:00
Note that the ` + " ` -- absolute ` " + ` parameter is useful for making lists of files
to pass to an rclone copy with the ` + " ` -- files - from - raw ` " + ` flag .
2018-06-03 11:42:34 +02:00
2021-11-04 12:50:43 +01:00
For example , to find all the files modified within one day and copy
2018-06-03 11:42:34 +02:00
those only ( without traversing the whole directory structure ) :
rclone lsf -- absolute -- files - only -- max - age 1 d / path / to / local > new_files
2020-04-03 11:36:24 +02:00
rclone copy -- files - from - raw new_files / path / to / local remote : path
2018-06-03 11:42:34 +02:00
2023-12-08 01:29:55 +01:00
The default time format is ` + " ` ' 2006 - 01 - 02 15 : 04 : 05 ' ` " + ` .
[ Other formats ] ( https : //pkg.go.dev/time#pkg-constants) can be specified with the ` + "`--time-format`" + ` flag.
Examples :
rclone lsf remote : path -- format pt -- time - format ' Jan 2 , 2006 at 3 : 04 pm ( MST ) '
rclone lsf remote : path -- format pt -- time - format ' 2006 - 01 - 02 15 : 04 : 05.000000000 '
rclone lsf remote : path -- format pt -- time - format ' 2006 - 01 - 02 T15 : 04 : 05.999999999 Z07 : 00 '
rclone lsf remote : path -- format pt -- time - format RFC3339
rclone lsf remote : path -- format pt -- time - format DateOnly
rclone lsf remote : path -- format pt -- time - format max
` + " ` -- time - format max ` " + ` will automatically truncate ` + "' ` 2006 - 01 - 02 15 : 04 : 05.000000000 ` '" + `
to the maximum precision supported by the remote .
2018-01-06 18:00:20 +01:00
` + lshelp . Help ,
2022-11-26 23:40:49 +01:00
Annotations : map [ string ] string {
"versionIntroduced" : "v1.40" ,
2023-07-10 19:34:10 +02:00
"groups" : "Filter,Listing" ,
2022-11-26 23:40:49 +01:00
} ,
2018-01-06 15:39:31 +01:00
Run : func ( command * cobra . Command , args [ ] string ) {
cmd . CheckArgs ( 1 , 1 , command , args )
fsrc := cmd . NewFsSrc ( args )
cmd . Run ( false , false , command , func ( ) error {
2018-05-13 13:15:05 +02:00
// Work out if the separatorFlag was supplied or not
separatorFlag := command . Flags ( ) . Lookup ( "separator" )
separatorFlagSupplied := separatorFlag != nil && separatorFlag . Changed
// Default the separator to , if using CSV
if csv && ! separatorFlagSupplied {
separator = ","
}
2019-06-17 10:34:30 +02:00
return Lsf ( context . Background ( ) , fsrc , os . Stdout )
2018-01-06 15:39:31 +01:00
} )
} ,
}
2018-01-06 18:00:20 +01:00
// Lsf lists all the objects in the path with modification time, size
// and path in specific format.
2019-06-17 10:34:30 +02:00
func Lsf ( ctx context . Context , fsrc fs . Fs , out io . Writer ) error {
2018-01-12 17:30:54 +01:00
var list operations . ListFormat
2018-01-06 18:00:20 +01:00
list . SetSeparator ( separator )
2018-05-13 13:15:05 +02:00
list . SetCSV ( csv )
2018-01-06 18:00:20 +01:00
list . SetDirSlash ( dirSlash )
2018-06-03 11:42:34 +02:00
list . SetAbsolute ( absolute )
2019-02-14 09:45:03 +01:00
var opt = operations . ListJSONOpt {
2020-01-26 17:38:00 +01:00
NoModTime : true ,
NoMimeType : true ,
DirsOnly : dirsOnly ,
FilesOnly : filesOnly ,
Recurse : recurse ,
2019-02-14 09:45:03 +01:00
}
2018-01-06 18:00:20 +01:00
for _ , char := range format {
switch char {
case 'p' :
list . AddPath ( )
case 't' :
2023-12-08 01:29:55 +01:00
if timeFormat == "max" {
timeFormat = operations . FormatForLSFPrecision ( fsrc . Precision ( ) )
}
list . AddModTime ( timeFormat )
2019-02-14 09:45:03 +01:00
opt . NoModTime = false
2018-01-06 18:00:20 +01:00
case 's' :
list . AddSize ( )
2018-01-06 18:53:37 +01:00
case 'h' :
list . AddHash ( hashType )
2019-02-14 09:45:03 +01:00
opt . ShowHash = true
2020-04-28 19:44:04 +02:00
opt . HashTypes = [ ] string { hashType . String ( ) }
2018-05-13 10:18:08 +02:00
case 'i' :
list . AddID ( )
2018-05-13 11:37:25 +02:00
case 'm' :
list . AddMimeType ( )
2020-01-26 17:38:00 +01:00
opt . NoMimeType = false
2019-02-14 09:45:03 +01:00
case 'e' :
list . AddEncrypted ( )
opt . ShowEncrypted = true
case 'o' :
list . AddOrigID ( )
opt . ShowOrigIDs = true
2019-03-20 13:45:06 +01:00
case 'T' :
list . AddTier ( )
2022-05-24 12:31:48 +02:00
case 'M' :
list . AddMetadata ( )
opt . Metadata = true
2018-01-06 18:00:20 +01:00
default :
2022-06-08 22:54:39 +02:00
return fmt . Errorf ( "unknown format character %q" , char )
2018-01-06 18:00:20 +01:00
}
}
2019-06-17 10:34:30 +02:00
return operations . ListJSON ( ctx , fsrc , "" , & opt , func ( item * operations . ListJSONItem ) error {
2024-02-06 17:02:03 +01:00
// Make size deterministic for tests
if item . IsDir {
item . Size = - 1
}
2019-02-14 09:45:03 +01:00
_ , _ = fmt . Fprintln ( out , list . Format ( item ) )
2018-01-06 15:39:31 +01:00
return nil
} )
}