1
0
mirror of https://github.com/rclone/rclone.git synced 2026-01-05 18:13:17 +00:00

lsf: add --time-format flag

Before this change, lsf's time format was hard-coded to "2006-01-02 15:04:05",
regardless of the Fs's precision. After this change, a new optional
--time-format flag is added to allow customizing the format (the default is
unchanged).

Examples:
	rclone lsf remote:path --format pt --time-format 'Jan 2, 2006 at 3:04pm (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-02T15:04:05.999999999Z07: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.
This commit is contained in:
nielash
2023-12-07 19:29:55 -05:00
parent b06935a12e
commit 66929416d4
4 changed files with 183 additions and 15 deletions

View File

@@ -17,21 +17,23 @@ import (
)
var (
format string
separator string
dirSlash bool
recurse bool
hashType = hash.MD5
filesOnly bool
dirsOnly bool
csv bool
absolute bool
format string
timeFormat string
separator string
dirSlash bool
recurse bool
hashType = hash.MD5
filesOnly bool
dirsOnly bool
csv bool
absolute bool
)
func init() {
cmd.Root.AddCommand(commandDefinition)
cmdFlags := commandDefinition.Flags()
flags.StringVarP(cmdFlags, &format, "format", "F", "p", "Output format - see help for details", "")
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)", "")
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", "")
@@ -141,6 +143,19 @@ those only (without traversing the whole directory structure):
rclone lsf --absolute --files-only --max-age 1d /path/to/local > new_files
rclone copy --files-from-raw new_files /path/to/local remote:path
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:04pm (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-02T15:04:05.999999999Z07: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.
` + lshelp.Help,
Annotations: map[string]string{
"versionIntroduced": "v1.40",
@@ -183,7 +198,10 @@ func Lsf(ctx context.Context, fsrc fs.Fs, out io.Writer) error {
case 'p':
list.AddPath()
case 't':
list.AddModTime()
if timeFormat == "max" {
timeFormat = operations.FormatForLSFPrecision(fsrc.Precision())
}
list.AddModTime(timeFormat)
opt.NoModTime = false
case 's':
list.AddSize()

View File

@@ -8,6 +8,7 @@ import (
_ "github.com/rclone/rclone/backend/local"
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/list"
"github.com/rclone/rclone/fs/operations"
"github.com/rclone/rclone/fstest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -223,3 +224,82 @@ subdir/file3_+_111_+_`+expectedOutput[6]+`
recurse = false
dirSlash = false
}
func TestTimeFormat(t *testing.T) {
fstest.Initialise()
f, err := fs.NewFs(context.Background(), "testfiles")
require.NoError(t, err)
format = "pst"
separator = "_+_"
recurse = true
dirSlash = true
timeFormat = "Jan 2, 2006 at 3:04pm (MST)"
buf := new(bytes.Buffer)
err = Lsf(context.Background(), f, buf)
require.NoError(t, err)
items, _ := list.DirSorted(context.Background(), f, true, "")
itemsInSubdir, _ := list.DirSorted(context.Background(), f, true, "subdir")
var expectedOutput []string
for _, item := range items {
expectedOutput = append(expectedOutput, item.ModTime(context.Background()).Format(timeFormat))
}
for _, item := range itemsInSubdir {
expectedOutput = append(expectedOutput, item.ModTime(context.Background()).Format(timeFormat))
}
assert.Equal(t, `file1_+_0_+_`+expectedOutput[0]+`
file2_+_321_+_`+expectedOutput[1]+`
file3_+_1234_+_`+expectedOutput[2]+`
subdir/_+_-1_+_`+expectedOutput[3]+`
subdir/file1_+_0_+_`+expectedOutput[4]+`
subdir/file2_+_1_+_`+expectedOutput[5]+`
subdir/file3_+_111_+_`+expectedOutput[6]+`
`, buf.String())
format = ""
separator = ""
recurse = false
dirSlash = false
}
func TestTimeFormatMax(t *testing.T) {
fstest.Initialise()
f, err := fs.NewFs(context.Background(), "testfiles")
require.NoError(t, err)
format = "pst"
separator = "_+_"
recurse = true
dirSlash = true
timeFormat = "max"
precision := operations.FormatForLSFPrecision(f.Precision())
buf := new(bytes.Buffer)
err = Lsf(context.Background(), f, buf)
require.NoError(t, err)
items, _ := list.DirSorted(context.Background(), f, true, "")
itemsInSubdir, _ := list.DirSorted(context.Background(), f, true, "subdir")
var expectedOutput []string
for _, item := range items {
expectedOutput = append(expectedOutput, item.ModTime(context.Background()).Format(precision))
}
for _, item := range itemsInSubdir {
expectedOutput = append(expectedOutput, item.ModTime(context.Background()).Format(precision))
}
assert.Equal(t, `file1_+_0_+_`+expectedOutput[0]+`
file2_+_321_+_`+expectedOutput[1]+`
file3_+_1234_+_`+expectedOutput[2]+`
subdir/_+_-1_+_`+expectedOutput[3]+`
subdir/file1_+_0_+_`+expectedOutput[4]+`
subdir/file2_+_1_+_`+expectedOutput[5]+`
subdir/file3_+_111_+_`+expectedOutput[6]+`
`, buf.String())
format = ""
separator = ""
recurse = false
dirSlash = false
}