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
This commit is contained in:
Nick Craig-Wood 2025-02-19 21:20:24 +00:00
parent 85d467e16a
commit 0ccf65017f
2 changed files with 17 additions and 8 deletions

View File

@ -51,6 +51,7 @@ unless ` + "`--no-create`" + ` or ` + "`--recursive`" + ` is provided.
If ` + "`--recursive`" + ` is used then recursively sets the modification If ` + "`--recursive`" + ` is used then recursively sets the modification
time on all existing files that is found under the path. Filters are supported, 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. 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 If ` + "`--timestamp`" + ` is used then sets the modification time to that
time instead of the current time. Times may be specified as one of: time instead of the current time. Times may be specified as one of:

View File

@ -2140,20 +2140,28 @@ func SetTierFile(ctx context.Context, o fs.Object, tier string) error {
// TouchDir touches every file in directory with time t // 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 { 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) { entries.ForObject(func(o fs.Object) {
if !SkipDestructive(ctx, o, "touch") { if !SkipDestructive(ctx, o, "touch") {
fs.Debugf(f, "Touching %q", o.Remote()) g.Go(func() error {
err := o.SetModTime(ctx, t) fs.Debugf(f, "Touching %q", o.Remote())
if err != nil { err := o.SetModTime(gCtx, t)
err = fmt.Errorf("failed to touch: %w", err) if err != nil {
err = fs.CountError(ctx, err) err = fmt.Errorf("failed to touch: %w", err)
fs.Errorf(o, "%v", err) err = fs.CountError(gCtx, err)
} fs.Errorf(o, "%v", err)
}
return nil
})
} }
}) })
return nil return nil
}) })
_ = g.Wait()
return err
} }
// ListFormat defines files information print format // ListFormat defines files information print format