Repository: rclone/rclone
Pull request #6882 (2023-03-23 23:03:24)

build(deps): bump github.com/aws/aws-sdk-go from 1.44.227 to 1.44.228
Bumps [github.com/aws/aws-sdk-go](https://github.com/aws/aws-sdk-go) from 1.44.227 to 1.44.228.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/aws/aws-sdk-go/releases">github.com/aws/aws-sdk-go's releases</a>.</em></p>
<blockquote>
<h1>Release v1.44.228 (2023-03-23)</h1>
<h3>Service Client Updates</h3>
<ul>
<li><code>service/batch</code>: Updates service API and documentation
<ul>
<li>This feature allows Batch to support configuration of ephemeral storage size for jobs running on FARGATE</li>
</ul>
</li>
<li><code>service/chime-sdk-identity</code>: Updates service API, documentation, and paginators</li>
<li><code>service/chime-sdk-media-pipelines</code>: Updates service API, documentation, and paginators</li>
<li><code>service/chime-sdk-messaging</code>: Updates service API and documentation</li>
<li><code>service/chime-sdk-voice</code>: Updates service API, documentation, and paginators</li>
<li><code>service/codeartifact</code>: Updates service API and documentation</li>
<li><code>service/guardduty</code>: Updates service API and documentation
<ul>
<li>Adds AutoEnableOrganizationMembers attribute to DescribeOrganizationConfiguration and UpdateOrganizationConfiguration APIs.</li>
</ul>
</li>
<li><code>service/ivs-realtime</code>: Adds new service</li>
<li><code>service/mediaconvert</code>: Updates service API and documentation
<ul>
<li>AWS Elemental MediaConvert SDK now supports passthrough of ID3v2 tags for audio inputs to audio-only HLS outputs.</li>
</ul>
</li>
<li><code>service/sagemaker</code>: Updates service API and documentation
<ul>
<li>Amazon SageMaker Autopilot adds two new APIs - CreateAutoMLJobV2 and DescribeAutoMLJobV2. Amazon SageMaker Notebook Instances now supports the ml.geospatial.interactive instance type.</li>
</ul>
</li>
<li><code>service/servicediscovery</code>: Updates service API</li>
<li><code>service/textract</code>: Updates service API and documentation</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/aws/aws-sdk-go/commit/a109cad51140ee84887c49a6d13077e2df7dfbe0"><code>a109cad</code></a> Release v1.44.228 (2023-03-23) (<a href="https://redirect.github.com/aws/aws-sdk-go/issues/4772">#4772</a>)</li>
<li>See full diff in <a href="https://github.com/aws/aws-sdk-go/compare/v1.44.227...v1.44.228">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go&package-manager=go_modules&previous-version=1.44.227&new-version=1.44.228)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/backend/azureblob/azureblob.go b/backend/azureblob/azureblob.go
index 85bc208a6..ef5d22ade 100644
--- a/backend/azureblob/azureblob.go
+++ b/backend/azureblob/azureblob.go
@@ -690,7 +690,7 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
 		}
 		cred, err = azidentity.NewDefaultAzureCredential(&options)
 		if err != nil {
-			return nil, fmt.Errorf("create azure enviroment credential failed: %w", err)
+			return nil, fmt.Errorf("create azure environment credential failed: %w", err)
 		}
 	case opt.UseEmulator:
 		if opt.Account == "" {
diff --git a/backend/cache/cache.go b/backend/cache/cache.go
index dd16642c9..3a0bc05ae 100644
--- a/backend/cache/cache.go
+++ b/backend/cache/cache.go
@@ -1787,7 +1787,7 @@ func (f *Fs) CleanUpCache(ignoreLastTs bool) {
 	}
 }
 
-// StopBackgroundRunners will signall all the runners to stop their work
+// StopBackgroundRunners will signal all the runners to stop their work
 // can be triggered from a terminate signal or from testing between runs
 func (f *Fs) StopBackgroundRunners() {
 	f.cleanupChan <- false
diff --git a/backend/combine/combine.go b/backend/combine/combine.go
index 63fb4635e..f6763ee0d 100644
--- a/backend/combine/combine.go
+++ b/backend/combine/combine.go
@@ -1,4 +1,4 @@
-// Package combine implents a backend to combine multiple remotes in a directory tree
+// Package combine implements a backend to combine multiple remotes in a directory tree
 package combine
 
 /*
@@ -351,7 +351,7 @@ func (f *Fs) multithread(ctx context.Context, fn func(context.Context, *upstream
 	return g.Wait()
 }
 
-// join the elements together but unline path.Join return empty string
+// join the elements together but unlike path.Join return empty string
 func join(elem ...string) string {
 	result := path.Join(elem...)
 	if result == "." {
diff --git a/backend/crypt/cipher.go b/backend/crypt/cipher.go
index 017eabea8..f5a33b9a8 100644
--- a/backend/crypt/cipher.go
+++ b/backend/crypt/cipher.go
@@ -209,7 +209,7 @@ func (c *Cipher) setPassBadBlocks(passBadBlocks bool) {
 // scrypt.
 //
 // If salt is "" we use a fixed salt just to make attackers lives
-// slighty harder than using no salt.
+// slightly harder than using no salt.
 //
 // Note that empty password makes all 0x00 keys which is used in the
 // tests.
@@ -914,9 +914,8 @@ func (fh *decrypter) Read(p []byte) (n int, err error) {
 	return n, nil
 }
 
-// calculateUnderlying converts an (offset, limit) in a crypted file
-// into an (underlyingOffset, underlyingLimit) for the underlying
-// file.
+// calculateUnderlying converts an (offset, limit) in an encrypted file
+// into an (underlyingOffset, underlyingLimit) for the underlying file.
 //
 // It also returns number of bytes to discard after reading the first
 // block and number of blocks this is from the start so the nonce can
diff --git a/backend/crypt/crypt.go b/backend/crypt/crypt.go
index 22be1bb07..ce200801c 100644
--- a/backend/crypt/crypt.go
+++ b/backend/crypt/crypt.go
@@ -465,7 +465,7 @@ func (f *Fs) put(ctx context.Context, in io.Reader, src fs.ObjectInfo, options [
 				if err != nil {
 					fs.Errorf(o, "Failed to remove corrupted object: %v", err)
 				}
-				return nil, fmt.Errorf("corrupted on transfer: %v crypted hash differ src %q vs dst %q", ht, srcHash, dstHash)
+				return nil, fmt.Errorf("corrupted on transfer: %v encrypted hash differ src %q vs dst %q", ht, srcHash, dstHash)
 			}
 			fs.Debugf(src, "%v = %s OK", ht, srcHash)
 		}
diff --git a/backend/drive/drive.go b/backend/drive/drive.go
index c3cf25ded..5f1472ccf 100644
--- a/backend/drive/drive.go
+++ b/backend/drive/drive.go
@@ -202,7 +202,7 @@ func init() {
 					m.Set("root_folder_id", "appDataFolder")
 				}
 
-				if opt.ServiceAccountFile == "" && opt.ServiceAccountCredentials == "" {
+				if opt.ServiceAccountFile == "" && opt.ServiceAccountCredentials == "" && !opt.EnvAuth {
 					return oauthutil.ConfigOut("teamdrive", &oauthutil.Options{
 						OAuth2Config: driveConfig,
 					})
@@ -598,6 +598,18 @@ resource key is no needed.
 			// Encode invalid UTF-8 bytes as json doesn't handle them properly.
 			// Don't encode / as it's a valid name character in drive.
 			Default: encoder.EncodeInvalidUtf8,
+		}, {
+			Name:     "env_auth",
+			Help:     "Get IAM credentials from runtime (environment variables or instance meta data if no env vars).\n\nOnly applies if service_account_file and service_account_credentials is blank.",
+			Default:  false,
+			Advanced: true,
+			Examples: []fs.OptionExample{{
+				Value: "false",
+				Help:  "Enter credentials in the next step.",
+			}, {
+				Value: "true",
+				Help:  "Get GCP IAM credentials from the environment (env vars or IAM).",
+			}},
 		}}...),
 	})
 
@@ -654,6 +666,7 @@ type Options struct {
 	SkipDanglingShortcuts     bool                 `config:"skip_dangling_shortcuts"`
 	ResourceKey               string               `config:"resource_key"`
 	Enc                       encoder.MultiEncoder `config:"encoding"`
+	EnvAuth                   bool                 `config:"env_auth"`
 }
 
 // Fs represents a remote drive server
@@ -1122,6 +1135,12 @@ func createOAuthClient(ctx context.Context, opt *Options, name string, m configm
 		if err != nil {
 			return nil, fmt.Errorf("failed to create oauth client from service account: %w", err)
 		}
+	} else if opt.EnvAuth {
+		scopes := driveScopes(opt.Scope)
+		oAuthClient, err = google.DefaultClient(ctx, scopes...)
+		if err != nil {
+			return nil, fmt.Errorf("failed to create client from environment: %w", err)
+		}
 	} else {
 		oAuthClient, _, err = oauthutil.NewClientWithBaseClient(ctx, name, m, driveConfig, getClient(ctx, opt))
 		if err != nil {
diff --git a/backend/dropbox/dropbox.go b/backend/dropbox/dropbox.go
index 740bd76e3..d0eaabd2f 100644
--- a/backend/dropbox/dropbox.go
+++ b/backend/dropbox/dropbox.go
@@ -536,7 +536,7 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
 			default:
 				return nil, err
 			}
-			// if the moint failed we have to abort here
+			// if the mount failed we have to abort here
 		}
 		// if the mount succeeded it's now a normal folder in the users root namespace
 		// we disable shared folder mode and proceed normally
diff --git a/backend/fichier/api.go b/backend/fichier/api.go
index 1ee812c47..60b5c7f97 100644
--- a/backend/fichier/api.go
+++ b/backend/fichier/api.go
@@ -473,7 +473,7 @@ func (f *Fs) getUploadNode(ctx context.Context) (response *GetUploadNodeResponse
 		return shouldRetry(ctx, resp, err)
 	})
 	if err != nil {
-		return nil, fmt.Errorf("didnt got an upload node: %w", err)
+		return nil, fmt.Errorf("didn't get an upload node: %w", err)
 	}
 
 	// fs.Debugf(f, "Got Upload node")
diff --git a/backend/fichier/fichier.go b/backend/fichier/fichier.go
index e6c053051..f42e5a341 100644
--- a/backend/fichier/fichier.go
+++ b/backend/fichier/fichier.go
@@ -333,7 +333,7 @@ func (f *Fs) Put(ctx context.Context, in io.Reader, src fs.ObjectInfo, options .
 // checking to see if there is one already - use Put() for that.
 func (f *Fs) putUnchecked(ctx context.Context, in io.Reader, remote string, size int64, options ...fs.OpenOption) (fs.Object, error) {
 	if size > int64(300e9) {
-		return nil, errors.New("File too big, cant upload")
+		return nil, errors.New("File too big, can't upload")
 	} else if size == 0 {
 		return nil, fs.ErrorCantUploadEmptyFiles
 	}
diff --git a/backend/hidrive/hidrive.go b/backend/hidrive/hidrive.go
index 5004b8191..bf6637fca 100644
--- a/backend/hidrive/hidrive.go
+++ b/backend/hidrive/hidrive.go
@@ -2,7 +2,7 @@
 package hidrive
 
 // FIXME HiDrive only supports file or folder names of 255 characters or less.
-// Operations that create files oder folder with longer names will throw a HTTP error:
+// Operations that create files or folders with longer names will throw an HTTP error:
 // - 422 Unprocessable Entity
 // A more graceful way for rclone to handle this may be desirable.
 
diff --git a/backend/jottacloud/jottacloud.go b/backend/jottacloud/jottacloud.go
index bb775e198..ea83a5932 100644
--- a/backend/jottacloud/jottacloud.go
+++ b/backend/jottacloud/jottacloud.go
@@ -1930,7 +1930,7 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
 		o.md5 = result.Md5
 		o.modTime = time.Unix(result.Modified/1000, 0)
 	} else {
-		// If the file state is COMPLETE we don't need to upload it because the file was already found but we still ned to update our metadata
+		// If the file state is COMPLETE we don't need to upload it because the file was already found but we still need to update our metadata
 		return o.readMetaData(ctx, true)
 	}
 
diff --git a/backend/local/metadata_linux.go b/backend/local/metadata_linux.go
index b274148e7..9d9c43355 100644
--- a/backend/local/metadata_linux.go
+++ b/backend/local/metadata_linux.go
@@ -91,7 +91,7 @@ func readMetadataFromFileFstatat(o *Object, m *fs.Metadata) (err error) {
 		// The types of t.Sec and t.Nsec vary from int32 to int64 on
 		// different Linux architectures so we need to cast them to
 		// int64 here and hence need to quiet the linter about
-		// unecessary casts.
+		// unnecessary casts.
 		//
 		// nolint: unconvert
 		m.Set(key, time.Unix(int64(t.Sec), int64(t.Nsec)).Format(metadataTimeFormat))
diff --git a/backend/mega/mega.go b/backend/mega/mega.go
index d9a218eee..d2f3b5ac1 100644
--- a/backend/mega/mega.go
+++ b/backend/mega/mega.go
@@ -90,7 +90,7 @@ permanently delete objects instead.`,
 MEGA uses plain text HTTP connections by default.
 Some ISPs throttle HTTP connections, this causes transfers to become very slow.
 Enabling this will force MEGA to use HTTPS for all transfers.
-HTTPS is normally not necesary since all data is already encrypted anyway.
+HTTPS is normally not necessary since all data is already encrypted anyway.
 Enabling it will increase CPU usage and add network overhead.`,
 			Default:  false,
 			Advanced: true,
diff --git a/backend/s3/s3.go b/backend/s3/s3.go
index c7b09e631..14bf5ceba 100644
--- a/backend/s3/s3.go
+++ b/backend/s3/s3.go
@@ -1,4 +1,4 @@
-// Package s3 provides an interface to Amazon S3 oject storage
+// Package s3 provides an interface to Amazon S3 object storage
 package s3
 
 //go:generate go run gen_setfrom.go -o setfrom.go
@@ -2998,7 +2998,7 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
 		return nil, fmt.Errorf("s3: upload cutoff: %w", err)
 	}
 	if opt.Versions && opt.VersionAt.IsSet() {
-		return nil, errors.New("s3: cant use --s3-versions and --s3-version-at at the same time")
+		return nil, errors.New("s3: can't use --s3-versions and --s3-version-at at the same time")
 	}
 	if opt.BucketACL == "" {
 		opt.BucketACL = opt.ACL
diff --git a/cmd/check/check.go b/cmd/check/check.go
index 3c126e176..8251d8e47 100644
--- a/cmd/check/check.go
+++ b/cmd/check/check.go
@@ -72,6 +72,9 @@ you what happened to it. These are reminiscent of diff files.
 - |+ path| means path was missing on the destination, so only in the source
 - |* path| means path was present in source and destination but different.
 - |! path| means there was an error reading or hashing the source or dest.
+
+The default number of parallel checks is 8. See the [--checkers=N](/docs/#checkers-n)
+option for more information.
 `, "|", "`")
 
 // GetCheckOpt gets the options corresponding to the check flags
@@ -142,7 +145,7 @@ match.  It doesn't alter the source or destination.
 
 For the [crypt](/crypt/) remote there is a dedicated command,
 [cryptcheck](/commands/rclone_cryptcheck/), that are able to check
-the checksums of the crypted files.
+the checksums of the encrypted files.
 
 If you supply the |--size-only| flag, it will only compare the sizes not
 the hashes as well.  Use this for a quick check.
diff --git a/cmd/cryptcheck/cryptcheck.go b/cmd/cryptcheck/cryptcheck.go
index 481c4cece..7c01d9d59 100644
--- a/cmd/cryptcheck/cryptcheck.go
+++ b/cmd/cryptcheck/cryptcheck.go
@@ -22,11 +22,11 @@ func init() {
 
 var commandDefinition = &cobra.Command{
 	Use:   "cryptcheck remote:path cryptedremote:path",
-	Short: `Cryptcheck checks the integrity of a crypted remote.`,
+	Short: `Cryptcheck checks the integrity of an encrypted remote.`,
 	Long: `
 rclone cryptcheck checks a remote against a [crypted](/crypt/) remote.
 This is the equivalent of running rclone [check](/commands/rclone_check/),
-but able to check the checksums of the crypted remote.
+but able to check the checksums of the encrypted remote.
 
 For it to work the underlying remote of the cryptedremote must support
 some kind of checksum.
@@ -59,7 +59,7 @@ After it has run it will log the status of the encryptedremote:.
 	},
 }
 
-// cryptCheck checks the integrity of a crypted remote
+// cryptCheck checks the integrity of an encrypted remote
 func cryptCheck(ctx context.Context, fdst, fsrc fs.Fs) error {
 	// Check to see fcrypt is a crypt
 	fcrypt, ok := fdst.(*crypt.Fs)
diff --git a/cmd/serve/sftp/sftp.go b/cmd/serve/sftp/sftp.go
index 2a255224b..ce0c235c7 100644
--- a/cmd/serve/sftp/sftp.go
+++ b/cmd/serve/sftp/sftp.go
@@ -108,7 +108,7 @@ which can lead to "corrupted on transfer" errors. This is the case because
 the client chooses indiscriminately which server to send commands to while
 the servers all have different views of the state of the filing system.
 
-The "restrict" in authorized_keys prevents SHA1SUMs and MD5SUMs from beeing
+The "restrict" in authorized_keys prevents SHA1SUMs and MD5SUMs from being
 used. Omitting "restrict" and using  ` + "`--sftp-path-override`" + ` to enable
 checksumming is possible but less secure and you could use the SFTP server
 provided by OpenSSH in this case.
diff --git a/cmd/touch/touch.go b/cmd/touch/touch.go
index 5dcf123e3..6b6cdcea9 100644
--- a/cmd/touch/touch.go
+++ b/cmd/touch/touch.go
@@ -141,7 +141,7 @@ func Touch(ctx context.Context, f fs.Fs, remote string) error {
 	file, err := f.NewObject(ctx, remote)
 	if err != nil {
 		if errors.Is(err, fs.ErrorObjectNotFound) {
-			// Touching non-existant path, possibly creating it as new file
+			// Touching non-existent path, possibly creating it as new file
 			if remote == "" {
 				fs.Logf(f, "Not touching empty directory")
 				return nil
diff --git a/docs/content/authors.md b/docs/content/authors.md
index cda1d4f22..1904ddd40 100644
--- a/docs/content/authors.md
+++ b/docs/content/authors.md
@@ -13,7 +13,7 @@ Authors
 Contributors
 ------------
 
-{{< rem `email addresses removed from here need to be addeed to
+{{< rem `email addresses removed from here need to be added to
 bin/.ignore-emails to make sure update-authors.py doesn't immediately
 put them back in again.` >}}
 
diff --git a/docs/content/bisync.md b/docs/content/bisync.md
index df88cf87e..f8d0c440f 100644
--- a/docs/content/bisync.md
+++ b/docs/content/bisync.md
@@ -596,7 +596,7 @@ quashed by adding `--quiet` to the bisync command line.
 # NOTICE: If you make changes to this file you MUST do a --resync run.
 #         Run with --dry-run to see what changes will be made.
 
-# Dropbox wont sync some files so filter them away here.
+# Dropbox won't sync some files so filter them away here.
 # See https://help.dropbox.com/installs-integrations/sync-uploads/files-not-syncing
 - .dropbox.attr
 - ~*.tmp
@@ -1008,7 +1008,7 @@ Your normal workflow might be as follows:
   Delete a single file.
 - `delete-glob <dir> <pattern>`
   Delete a group of files located one level deep in the given directory
-  with names maching a given glob pattern.
+  with names matching a given glob pattern.
 - `touch-glob YYYY-MM-DD <dir> <pattern>`
   Change modification time on a group of files.
 - `touch-copy YYYY-MM-DD <source-file> <dest-dir>`
diff --git a/docs/content/changelog.md b/docs/content/changelog.md
index da0b10208..5bdd596c3 100644
--- a/docs/content/changelog.md
+++ b/docs/content/changelog.md
@@ -2020,8 +2020,8 @@ all the docs and Edward Barker for helping re-write the front page.
     * Use proper import path go.etcd.io/bbolt (Robert-André Mauchin)
 * Crypt
     * Calculate hashes for uploads from local disk (Nick Craig-Wood)
-        * This allows crypted Jottacloud uploads without using local disk
-        * This means crypted s3/b2 uploads will now have hashes
+        * This allows encrypted Jottacloud uploads without using local disk
+        * This means encrypted s3/b2 uploads will now have hashes
     * Added `rclone backend decode`/`encode` commands to replicate functionality of `cryptdecode` (Anagh Kumar Baranwal)
     * Get rid of the unused Cipher interface as it obfuscated the code (Nick Craig-Wood)
 * Azure Blob
@@ -3231,7 +3231,7 @@ Point release to fix hubic and azureblob backends.
     * Fix panic when running without plex configs (Remus Bunduc)
     * Fix root folder caching (Remus Bunduc)
 * Crypt
-    * Check the crypted hash of files when uploading for extra data security
+    * Check the encrypted hash of files when uploading for extra data security
 * Dropbox
     * Make Dropbox for business folders accessible using an initial `/` in the path
 * Google Cloud Storage
@@ -3586,7 +3586,7 @@ Point release to fix hubic and azureblob backends.
 * New commands
     * `rcat` - read from standard input and stream upload
     * `tree` - shows a nicely formatted recursive listing
-    * `cryptdecode` - decode crypted file names (thanks ishuah)
+    * `cryptdecode` - decode encrypted file names (thanks ishuah)
     * `config show` - print the config file
     * `config file` - print the config file location
 * New Features
@@ -3890,7 +3890,7 @@ Point release to fix hubic and azureblob backends.
     * Fix `rclone move` command
         * Delete src files which already existed in dst
         * Fix deletion of src file when dst file older
-    * Fix `rclone check` on crypted file systems
+    * Fix `rclone check` on encrypted file systems
     * Make failed uploads not count as "Transferred"
     * Make sure high level retries show with `-q`
     * Use a vendor directory with godep for repeatable builds
diff --git a/docs/content/commands/rclone.md b/docs/content/commands/rclone.md
index f256d6f4f..e3a8ad857 100644
--- a/docs/content/commands/rclone.md
+++ b/docs/content/commands/rclone.md
@@ -47,7 +47,7 @@ See the [global flags page](/flags/) for global options not listed here.
 * [rclone copy](/commands/rclone_copy/)	 - Copy files from source to dest, skipping identical files.
 * [rclone copyto](/commands/rclone_copyto/)	 - Copy files from source to dest, skipping identical files.
 * [rclone copyurl](/commands/rclone_copyurl/)	 - Copy url content to dest.
-* [rclone cryptcheck](/commands/rclone_cryptcheck/)	 - Cryptcheck checks the integrity of a crypted remote.
+* [rclone cryptcheck](/commands/rclone_cryptcheck/)	 - Cryptcheck checks the integrity of an encrypted remote.
 * [rclone cryptdecode](/commands/rclone_cryptdecode/)	 - Cryptdecode returns unencrypted file names.
 * [rclone dedupe](/commands/rclone_dedupe/)	 - Interactively find duplicate filenames and delete/rename them.
 * [rclone delete](/commands/rclone_delete/)	 - Remove the files in path.
diff --git a/docs/content/commands/rclone_check.md b/docs/content/commands/rclone_check.md
index 112633fab..29d89f22c 100644
--- a/docs/content/commands/rclone_check.md
+++ b/docs/content/commands/rclone_check.md
@@ -18,7 +18,7 @@ match.  It doesn't alter the source or destination.
 
 For the [crypt](/crypt/) remote there is a dedicated command,
 [cryptcheck](/commands/rclone_cryptcheck/), that are able to check
-the checksums of the crypted files.
+the checksums of the encrypted files.
 
 If you supply the `--size-only` flag, it will only compare the sizes not
 the hashes as well.  Use this for a quick check.
@@ -52,6 +52,8 @@ you what happened to it. These are reminiscent of diff files.
 - `* path` means path was present in source and destination but different.
 - `! path` means there was an error reading or hashing the source or dest.
 
+The default number of parallel checks is N=8. See the [--checkers=N](/docs/#checkers-n) option
+for more information.
 
 ```
 rclone check source:path dest:path [flags]
diff --git a/docs/content/commands/rclone_cryptcheck.md b/docs/content/commands/rclone_cryptcheck.md
index 21528b029..31181f101 100644
--- a/docs/content/commands/rclone_cryptcheck.md
+++ b/docs/content/commands/rclone_cryptcheck.md
@@ -1,6 +1,6 @@
 ---
 title: "rclone cryptcheck"
-description: "Cryptcheck checks the integrity of a crypted remote."
+description: "Cryptcheck checks the integrity of an encrypted remote."
 slug: rclone_cryptcheck
 url: /commands/rclone_cryptcheck/
 versionIntroduced: v1.36
@@ -8,21 +8,21 @@ versionIntroduced: v1.36
 ---
 # rclone cryptcheck
 
-Cryptcheck checks the integrity of a crypted remote.
+Cryptcheck checks the integrity of an encrypted remote.
 
 ## Synopsis
 
 
-rclone cryptcheck checks a remote against a [crypted](/crypt/) remote.
+rclone cryptcheck checks a remote against an [encrypted](/crypt/) remote.
 This is the equivalent of running rclone [check](/commands/rclone_check/),
-but able to check the checksums of the crypted remote.
+but able to check the checksums of the encrypted remote.
 
-For it to work the underlying remote of the cryptedremote must support
+For it to work the underlying remote of the encryptedremote must support
 some kind of checksum.
 
-It works by reading the nonce from each file on the cryptedremote: and
+It works by reading the nonce from each file on the encryptedremote: and
 using that to encrypt each file on the remote:.  It then checks the
-checksum of the underlying file on the cryptedremote: against the
+checksum of the underlying file on the ercryptedremote: against the
 checksum of the file it has just encrypted.
 
 Use it like this
@@ -57,9 +57,11 @@ you what happened to it. These are reminiscent of diff files.
 - `* path` means path was present in source and destination but different.
 - `! path` means there was an error reading or hashing the source or dest.
 
+The default number of parallel checks is N=8. See the [--checkers=N](/docs/#checkers-n) option
+for more information.
 
 ```
-rclone cryptcheck remote:path cryptedremote:path [flags]
+rclone cryptcheck remote:path encryptedremote:path [flags]
 ```
 
 ## Options
diff --git a/docs/content/commands/rclone_serve_sftp.md b/docs/content/commands/rclone_serve_sftp.md
index 1e878c058..680a42014 100644
--- a/docs/content/commands/rclone_serve_sftp.md
+++ b/docs/content/commands/rclone_serve_sftp.md
@@ -59,7 +59,7 @@ which can lead to "corrupted on transfer" errors. This is the case because
 the client chooses indiscriminately which server to send commands to while
 the servers all have different views of the state of the filing system.
 
-The "restrict" in authorized_keys prevents SHA1SUMs and MD5SUMs from beeing
+The "restrict" in authorized_keys prevents SHA1SUMs and MD5SUMs from being
 used. Omitting "restrict" and using  `--sftp-path-override` to enable
 checksumming is possible but less secure and you could use the SFTP server
 provided by OpenSSH in this case.
diff --git a/docs/content/crypt.md b/docs/content/crypt.md
index 6bc73dfe9..4a5eca211 100644
--- a/docs/content/crypt.md
+++ b/docs/content/crypt.md
@@ -414,7 +414,7 @@ Hashes are not stored for crypt. However the data integrity is
 protected by an extremely strong crypto authenticator.
 
 Use the `rclone cryptcheck` command to check the
-integrity of a crypted remote instead of `rclone check` which can't
+integrity of an encrypted remote instead of `rclone check` which can't
 check the checksums properly.
 
 {{< rem autogenerated options start" - DO NOT EDIT - instead edit fs.RegInfo in backend/crypt/crypt.go then run make backenddocs" >}}
@@ -640,9 +640,9 @@ Usage Example:
 
 {{< rem autogenerated options stop >}}
 
-## Backing up a crypted remote
+## Backing up an encrypted remote
 
-If you wish to backup a crypted remote, it is recommended that you use
+If you wish to backup an encrypted remote, it is recommended that you use
 `rclone sync` on the encrypted files, and make sure the passwords are
 the same in the new encrypted remote.
 
diff --git a/docs/content/docs.md b/docs/content/docs.md
index 5a9f441fb..9084a7b26 100644
--- a/docs/content/docs.md
+++ b/docs/content/docs.md
@@ -840,7 +840,7 @@ they are incorrect as it would normally.
 
 ### --color WHEN ###
 
-Specifiy when colors (and other ANSI codes) should be added to the output.
+Specify when colors (and other ANSI codes) should be added to the output.
 
 `AUTO` (default) only allows ANSI codes when the output is a terminal
 
@@ -947,6 +947,20 @@ You may also choose to [encrypt](#configuration-encryption) the file.
 When token-based authentication are used, the configuration file
 must be writable, because rclone needs to update the tokens inside it.
 
+To reduce risk of corrupting an existing configuration file, rclone
+will not write directly to it when saving changes. Instead it will
+first write to a new, temporary, file. If a configuration file already
+existed, it will (on Unix systems) try to mirror its permissions to
+the new file. Then it will rename the existing file by adding suffix
+".old" to its name (e.g. `rclone.conf.old`), if a file with the same
+name already exists it will simply be replaced. Next, rclone will rename
+the new file to the correct name, before finally cleaning up by deleting
+the original file now which has now ".old" suffix to its name. Note that
+one side-effect of this is that if you happen to have a file in the same
+directory and with the same name as your configuration file, but with
+suffix ".old", then rclone will end up deleting this file next time it
+updates its configuration file!
+
 ### --contimeout=TIME ###
 
 Set the connection timeout. This should be in go time format which
diff --git a/docs/content/drive.md b/docs/content/drive.md
index 7975cf6b9..c687315e9 100644
--- a/docs/content/drive.md
+++ b/docs/content/drive.md
@@ -227,12 +227,9 @@ There's a few steps we need to go through to accomplish this:
 [Google Developer Console](https://console.developers.google.com).
   - You must have a project - create one if you don't.
   - Then go to "IAM & admin" -> "Service Accounts".
-  - Use the "Create Credentials" button. Fill in "Service account name"
-with something that identifies your client. "Role" can be empty.
-  - Tick "Furnish a new private key" - select "Key type JSON".
-  - Tick "Enable G Suite Domain-wide Delegation". This option makes
-"impersonation" possible, as documented here:
-[Delegating domain-wide authority to the service account](https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority)
+  - Use the "Create Service Account" button. Fill in "Service account name"
+and "Service account ID" with something that identifies your client.
+  - Select "Create And Continue". Step 2 and 3 are optional.
   - These credentials are what rclone will use for authentication.
 If you ever need to remove access, press the "Delete service
 account key" button.
diff --git a/docs/content/filtering.md b/docs/content/filtering.md
index d61bb1992..12332dfeb 100644
--- a/docs/content/filtering.md
+++ b/docs/content/filtering.md
@@ -166,7 +166,7 @@ Which will match a directory called `start` with a file called
 `end.jpg` in it as the `.*` will match `/` characters.
 
 Note that you can use `-vv --dump filters` to show the filter patterns
-in regexp format - rclone implements the glob patters by transforming
+in regexp format - rclone implements the glob patterns by transforming
 them into regular expressions.
 
 ## Filter pattern examples {#examples}
diff --git a/docs/content/hasher.md b/docs/content/hasher.md
index 324f2b85f..f2606fc01 100644
--- a/docs/content/hasher.md
+++ b/docs/content/hasher.md
@@ -341,6 +341,6 @@ directory, usually `~/.cache/rclone/kv/`. Databases are maintained
 one per _base_ backend, named like `BaseRemote~hasher.bolt`.
 Checksums for multiple `alias`-es into a single base backend
 will be stored in the single database. All local paths are treated as
-aliases into the `local` backend (unless crypted or chunked) and stored
+aliases into the `local` backend (unless encrypted or chunked) and stored
 in `~/.cache/rclone/kv/local~hasher.bolt`.
 Databases can be shared between multiple rclone processes.
diff --git a/docs/content/install.md b/docs/content/install.md
index b8ec4c420..5f34af3d3 100644
--- a/docs/content/install.md
+++ b/docs/content/install.md
@@ -263,10 +263,16 @@ Here are some commands tested on an Ubuntu 18.04.3 host:
 # config on host at ~/.config/rclone/rclone.conf
 # data on host at ~/data
 
+# add a remote interactively
+docker run --rm -it \
+    --volume ~/.config/rclone:/config/rclone \
+    --user $(id -u):$(id -g) \
+    rclone/rclone \
+    config
+
 # make sure the config is ok by listing the remotes
 docker run --rm \
     --volume ~/.config/rclone:/config/rclone \
-    --volume ~/data:/data:shared \
     --user $(id -u):$(id -g) \
     rclone/rclone \
     listremotes
diff --git a/docs/content/jottacloud.md b/docs/content/jottacloud.md
index 24bcda7e9..787396919 100644
--- a/docs/content/jottacloud.md
+++ b/docs/content/jottacloud.md
@@ -244,7 +244,7 @@ Small files will be cached in memory - see the
 [--jottacloud-md5-memory-limit](#jottacloud-md5-memory-limit) flag.
 When uploading from local disk the source checksum is always available,
 so this does not apply. Starting with rclone version 1.52 the same is
-true for crypted remotes (in older versions the crypt backend would not
+true for encrypted remotes (in older versions the crypt backend would not
 calculate hashes for uploads from local disk, so the Jottacloud
 backend had to do it as described above).
 
diff --git a/docs/content/mega.md b/docs/content/mega.md
index 8326f1fcb..9c31e80e0 100644
--- a/docs/content/mega.md
+++ b/docs/content/mega.md
@@ -259,7 +259,7 @@ Use HTTPS for transfers.
 MEGA uses plain text HTTP connections by default.
 Some ISPs throttle HTTP connections, this causes transfers to become very slow.
 Enabling this will force MEGA to use HTTPS for all transfers.
-HTTPS is normally not necesary since all data is already encrypted anyway.
+HTTPS is normally not necessary since all data is already encrypted anyway.
 Enabling it will increase CPU usage and add network overhead.
 
 Properties:
diff --git a/docs/content/smb.md b/docs/content/smb.md
index b55cdba5a..3ee6efe10 100644
--- a/docs/content/smb.md
+++ b/docs/content/smb.md
@@ -16,7 +16,7 @@ command.)  You may put subdirectories in too, e.g. `remote:item/path/to/dir`.
 ## Notes
 
 The first path segment must be the name of the share, which you entered when you started to share on Windows. On smbd, it's the section title in `smb.conf` (usually in `/etc/samba/`) file.
-You can find shares by quering the root if you're unsure (e.g. `rclone lsd remote:`).
+You can find shares by querying the root if you're unsure (e.g. `rclone lsd remote:`).
 
 You can't access to the shared printers from rclone, obviously.
 
diff --git a/fs/operations/rc.go b/fs/operations/rc.go
index a4e15ea09..16942bea3 100644
--- a/fs/operations/rc.go
+++ b/fs/operations/rc.go
@@ -170,9 +170,9 @@ func init() {
 			Title: name + " a file from source remote to destination remote",
 			Help: `This takes the following parameters:
 
-- srcFs - a remote name string e.g. "drive:" for the source
+- srcFs - a remote name string e.g. "drive:" for the source, "/" for local filesystem
 - srcRemote - a path within that remote e.g. "file.txt" for the source
-- dstFs - a remote name string e.g. "drive2:" for the destination
+- dstFs - a remote name string e.g. "drive2:" for the destination, "/" for local filesystem
 - dstRemote - a path within that remote e.g. "file2.txt" for the destination
 `,
 		})
diff --git a/go.mod b/go.mod
index b8c8b14a7..ddc395619 100644
--- a/go.mod
+++ b/go.mod
@@ -17,7 +17,7 @@ require (
 	github.com/anacrolix/log v0.13.1
 	github.com/artyom/mtab v1.0.0
 	github.com/atotto/clipboard v0.1.4
-	github.com/aws/aws-sdk-go v1.44.227
+	github.com/aws/aws-sdk-go v1.44.228
 	github.com/buengese/sgzip v0.1.1
 	github.com/colinmarc/hdfs/v2 v2.3.0
 	github.com/coreos/go-semver v0.3.1
diff --git a/go.sum b/go.sum
index ac9af157e..aecaa1161 100644
--- a/go.sum
+++ b/go.sum
@@ -86,8 +86,8 @@ github.com/artyom/mtab v1.0.0 h1:r7OSVo5Jeqi8+LotZ0rT2kzfPIBp9KCpEJP8RQqGmSE=
 github.com/artyom/mtab v1.0.0/go.mod h1:EHpkp5OmPfS1yZX+/DFTztlJ9di5UzdDLX1/XzWPXw8=
 github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
 github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
-github.com/aws/aws-sdk-go v1.44.227 h1:HWNpINBu20yyfEXGHHSIsB955KUjWmZJETqnLIXizN4=
-github.com/aws/aws-sdk-go v1.44.227/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
+github.com/aws/aws-sdk-go v1.44.228 h1:CkkAlgNFf7qPZy/bAssF6lafR/ThMiiwKQEHVfPJixc=
+github.com/aws/aws-sdk-go v1.44.228/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
diff --git a/lib/buildinfo/arch.go b/lib/buildinfo/arch.go
index 7b565f558..c69b4ff9c 100644
--- a/lib/buildinfo/arch.go
+++ b/lib/buildinfo/arch.go
@@ -26,7 +26,7 @@ import (
 func GetSupportedGOARM() int {
 	if runtime.GOARCH == "arm" && cpu.Initialized {
 		// This CPU is an ARM (32-bit), and cpu.Initialized true means its
-		// features could be retrived on current GOOS so that we can check
+		// features could be retrieved on current GOOS so that we can check
 		// for floating point hardware support.
 		if cpu.ARM.HasVFPv3 {
 			// This CPU has VFPv3 floating point hardware, which means it can
diff --git a/lib/dircache/dircache.go b/lib/dircache/dircache.go
index 8076e7c8f..8cab02453 100644
--- a/lib/dircache/dircache.go
+++ b/lib/dircache/dircache.go
@@ -48,7 +48,7 @@ type DirCacher interface {
 // error. This isn't done at initialization as it isn't known whether
 // the root and intermediate directories need to be created or not.
 //
-// Most of the utility functions wil call FindRoot() on the caller's
+// Most of the utility functions will call FindRoot() on the caller's
 // behalf with the create flag passed in.
 //
 // The cache is safe for concurrent use
diff --git a/lib/errors/errors.go b/lib/errors/errors.go
index a978909ab..ea8d70318 100644
--- a/lib/errors/errors.go
+++ b/lib/errors/errors.go
@@ -1,4 +1,4 @@
-// Package errors provides error handling utilites.
+// Package errors provides error handling utilities.
 package errors
 
 import (
diff --git a/lib/terminal/terminal.go b/lib/terminal/terminal.go
index f933de719..e695dac70 100644
--- a/lib/terminal/terminal.go
+++ b/lib/terminal/terminal.go
@@ -116,7 +116,7 @@ func Write(out []byte) {
 // This enables virtual terminal processing on Windows 10 console,
 // adding native support for VT100 escape codes. When this terminal
 // package is used for output, the result is that the colorable library
-// don't have to decode the escapes and explicitely write text with color
+// don't have to decode the escapes and explicitly write text with color
 // formatting to the console using Windows API functions, but can simply
 // relay everything to stdout.
 func EnableColorsStdout() {
diff --git a/vfs/help.go b/vfs/help.go
index 84ad2dc9d..fe3c5f2a9 100644
--- a/vfs/help.go
+++ b/vfs/help.go
@@ -86,7 +86,7 @@ find that you need one or the other or both.
 
     --cache-dir string                   Directory rclone will use for caching.
     --vfs-cache-mode CacheMode           Cache mode off|minimal|writes|full (default off)
-    --vfs-cache-max-age duration         Max age of objects in the cache (default 1h0m0s)
+    --vfs-cache-max-age duration         Max time since last access of objects in the cache (default 1h0m0s)
     --vfs-cache-max-size SizeSuffix      Max total size of objects in the cache (default off)
     --vfs-cache-poll-interval duration   Interval to poll the cache for stale objects (default 1m0s)
     --vfs-write-back duration            Time to writeback files after last use when using cache (default 5s)
@@ -109,7 +109,18 @@ flags.
 If using !--vfs-cache-max-size! note that the cache may exceed this size
 for two reasons.  Firstly because it is only checked every
 !--vfs-cache-poll-interval!.  Secondly because open files cannot be
-evicted from the cache.
+evicted from the cache. When !--vfs-cache-max-size!
+is exceeded, rclone will attempt to evict the least accessed files
+from the cache first. rclone will start with files that haven't
+been accessed for the longest. This cache flushing strategy is
+efficient and more relevant files are likely to remain cached.
+
+The !--vfs-cache-max-age! will evict files from the cache
+after the set time since last access has passed. The default value of
+1 hour will start evicting files from cache that haven't been accessed
+for 1 hour. When a cached file is accessed the 1 hour timer is reset to 0
+and will wait for 1 more hour before evicting. Specify the time with
+standard notation, s, m, h, d, w .
 
 You **should not** run two copies of rclone using the same VFS cache
 with the same or overlapping remotes if using !--vfs-cache-mode > off!.
diff --git a/vfs/vfsflags/vfsflags.go b/vfs/vfsflags/vfsflags.go
index ccdcb17db..b4682f785 100644
--- a/vfs/vfsflags/vfsflags.go
+++ b/vfs/vfsflags/vfsflags.go
@@ -26,7 +26,7 @@ func AddFlags(flagSet *pflag.FlagSet) {
 	flags.BoolVarP(flagSet, &Opt.ReadOnly, "read-only", "", Opt.ReadOnly, "Only allow read-only access")
 	flags.FVarP(flagSet, &Opt.CacheMode, "vfs-cache-mode", "", "Cache mode off|minimal|writes|full")
 	flags.DurationVarP(flagSet, &Opt.CachePollInterval, "vfs-cache-poll-interval", "", Opt.CachePollInterval, "Interval to poll the cache for stale objects")
-	flags.DurationVarP(flagSet, &Opt.CacheMaxAge, "vfs-cache-max-age", "", Opt.CacheMaxAge, "Max age of objects in the cache")
+	flags.DurationVarP(flagSet, &Opt.CacheMaxAge, "vfs-cache-max-age", "", Opt.CacheMaxAge, "Max time since last access of objects in the cache")
 	flags.FVarP(flagSet, &Opt.CacheMaxSize, "vfs-cache-max-size", "", "Max total size of objects in the cache")
 	flags.FVarP(flagSet, &Opt.ChunkSize, "vfs-read-chunk-size", "", "Read the source objects in chunks")
 	flags.FVarP(flagSet, &Opt.ChunkSizeLimit, "vfs-read-chunk-size-limit", "", "If greater than --vfs-read-chunk-size, double the chunk size after each chunk read, until the limit is reached ('off' is unlimited)")


Test patch:
diff --git a/cmd/bisync/testdata/test_check_access_filters/scenario.txt b/cmd/bisync/testdata/test_check_access_filters/scenario.txt
index 46948a468..f29806ba6 100644
--- a/cmd/bisync/testdata/test_check_access_filters/scenario.txt
+++ b/cmd/bisync/testdata/test_check_access_filters/scenario.txt
@@ -3,8 +3,8 @@ test check-access-filters
 # NOTE: Include Other tests may result in listing diffs due to rclone processing order change. False fail.
 #
 # Tests are done in two phases:
-#  - EXCLUDE OTHER tests check that RCLONE_TEST files are only found in the explicity included directories
-#  - INCLUDE OTHER tesss check that RCLONE_TEST files are found in all directories not explicity excluded
+#  - EXCLUDE OTHER tests check that RCLONE_TEST files are only found in the explicitly included directories
+#  - INCLUDE OTHER tesss check that RCLONE_TEST files are found in all directories not explicitly excluded
 #
 # Each phase checks that:
 #  - missing RCLONE_TEST files in don't care directories don't cause failures
diff --git a/cmd/test/test.go b/cmd/test/test.go
index 8888f85c6..381d5681a 100644
--- a/cmd/test/test.go
+++ b/cmd/test/test.go
@@ -16,7 +16,7 @@ var Command = &cobra.Command{
 	Short: `Run a test command`,
 	Long: `Rclone test is used to run test commands.
 
-Select which test comand you want with the subcommand, eg
+Select which test command you want with the subcommand, eg
 
     rclone test memory remote:
 
diff --git a/cmdtest/cmdtest_test.go b/cmdtest/cmdtest_test.go
index c8870258c..f77ce9d93 100644
--- a/cmdtest/cmdtest_test.go
+++ b/cmdtest/cmdtest_test.go
@@ -43,7 +43,7 @@ const rcloneTestMain = "RCLONE_TEST_MAIN"
 
 // rcloneExecMain calls rclone with the given environment and arguments.
 // The environment variables are in a single string separated by ;
-// The terminal output is retuned as a string.
+// The terminal output is returned as a string.
 func rcloneExecMain(env string, args ...string) (string, error) {
 	_, found := os.LookupEnv(rcloneTestMain)
 	if !found {
@@ -62,7 +62,7 @@ func rcloneExecMain(env string, args ...string) (string, error) {
 // rcloneEnv calls rclone with the given environment and arguments.
 // The environment variables are in a single string separated by ;
 // The test config file is automatically configured in RCLONE_CONFIG.
-// The terminal output is retuned as a string.
+// The terminal output is returned as a string.
 func rcloneEnv(env string, args ...string) (string, error) {
 	envConfig := env
 	if testConfig != "" {
@@ -76,7 +76,7 @@ func rcloneEnv(env string, args ...string) (string, error) {
 
 // rclone calls rclone with the given arguments, E.g. "version","--help".
 // The test config file is automatically configured in RCLONE_CONFIG.
-// The terminal output is retuned as a string.
+// The terminal output is returned as a string.
 func rclone(args ...string) (string, error) {
 	return rcloneEnv("", args...)
 }
diff --git a/docs/content/commands/rclone_test.md b/docs/content/commands/rclone_test.md
index 4eed2b262..e9181d625 100644
--- a/docs/content/commands/rclone_test.md
+++ b/docs/content/commands/rclone_test.md
@@ -14,7 +14,7 @@ Run a test command
 
 Rclone test is used to run test commands.
 
-Select which test comand you want with the subcommand, eg
+Select which test command you want with the subcommand, eg
 
     rclone test memory remote: