From 0ccf65017f0801929d972f634111ca3b5f924e69 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Wed, 19 Feb 2025 21:20:24 +0000 Subject: [PATCH] touch: make touch obey --transfers Before this change, when executed on a directory, rclone would only touch files sequentially. This change makes rclone touch --transfers files at once. Fixes #8402 --- cmd/touch/touch.go | 1 + fs/operations/operations.go | 24 ++++++++++++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/cmd/touch/touch.go b/cmd/touch/touch.go index 913d052a8..f5048a6da 100644 --- a/cmd/touch/touch.go +++ b/cmd/touch/touch.go @@ -51,6 +51,7 @@ unless ` + "`--no-create`" + ` or ` + "`--recursive`" + ` is provided. If ` + "`--recursive`" + ` is used then recursively sets the modification time on all existing files that is found under the path. Filters are supported, and you can test with the ` + "`--dry-run`" + ` or the ` + "`--interactive`/`-i`" + ` flag. +This will touch ` + "`--transfers`" + ` files concurrently. If ` + "`--timestamp`" + ` is used then sets the modification time to that time instead of the current time. Times may be specified as one of: diff --git a/fs/operations/operations.go b/fs/operations/operations.go index 279c24076..df9ea88da 100644 --- a/fs/operations/operations.go +++ b/fs/operations/operations.go @@ -2140,20 +2140,28 @@ func SetTierFile(ctx context.Context, o fs.Object, tier string) error { // TouchDir touches every file in directory with time t func TouchDir(ctx context.Context, f fs.Fs, remote string, t time.Time, recursive bool) error { - return walk.ListR(ctx, f, remote, false, ConfigMaxDepth(ctx, recursive), walk.ListObjects, func(entries fs.DirEntries) error { + ci := fs.GetConfig(ctx) + g, gCtx := errgroup.WithContext(ctx) + g.SetLimit(ci.Transfers) + err := walk.ListR(ctx, f, remote, false, ConfigMaxDepth(ctx, recursive), walk.ListObjects, func(entries fs.DirEntries) error { entries.ForObject(func(o fs.Object) { if !SkipDestructive(ctx, o, "touch") { - fs.Debugf(f, "Touching %q", o.Remote()) - err := o.SetModTime(ctx, t) - if err != nil { - err = fmt.Errorf("failed to touch: %w", err) - err = fs.CountError(ctx, err) - fs.Errorf(o, "%v", err) - } + g.Go(func() error { + fs.Debugf(f, "Touching %q", o.Remote()) + err := o.SetModTime(gCtx, t) + if err != nil { + err = fmt.Errorf("failed to touch: %w", err) + err = fs.CountError(gCtx, err) + fs.Errorf(o, "%v", err) + } + return nil + }) } }) return nil }) + _ = g.Wait() + return err } // ListFormat defines files information print format