Repository: rclone/rclone
Pull request #7777 (2024-04-17 21:48:17)

backend http: Adding no-escape flag for option to not escape URL meta characters in path names - fixes issue #7637
#### What is the purpose of this change?

<!--
Fix for issue #7637, adding flag for http remotes "no-escape" allowing users to toggle between the default behavior of escaping these characters from paths or not.
-->

#### Was the change discussed in an issue or in the forum before?

<!--
issue #7637 
-->

#### Checklist

- [x] I have read the [contribution guidelines](https://github.com/rclone/rclone/blob/master/CONTRIBUTING.md#submitting-a-new-feature-or-bug-fix).
- [x] I have added tests for all changes in this PR if appropriate.
- [x] I have added documentation for the changes if appropriate.
- [x] All commit messages are in [house style](https://github.com/rclone/rclone/blob/master/CONTRIBUTING.md#commit-messages).
- [x] I'm done, this Pull Request is ready for review :-)



Patch:
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 675f1c87d..5c1136d5d 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -168,14 +168,6 @@ jobs:
           printf "\n\nSystem environment:\n\n"
           env
 
-      - name: Go module cache
-        uses: actions/cache@v4
-        with:
-          path: ~/go/pkg/mod
-          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
-          restore-keys: |
-            ${{ runner.os }}-go-
-
       - name: Build rclone
         shell: bash
         run: |
@@ -271,14 +263,6 @@ jobs:
         with:
           go-version: '>=1.22.0-rc.1'
 
-      - name: Go module cache
-        uses: actions/cache@v4
-        with:
-          path: ~/go/pkg/mod
-          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
-          restore-keys: |
-            ${{ runner.os }}-go-
-
       - name: Set global environment variables
         shell: bash
         run: |
diff --git a/.github/workflows/winget.yml b/.github/workflows/winget.yml
index 6a2264b93..378e45a45 100644
--- a/.github/workflows/winget.yml
+++ b/.github/workflows/winget.yml
@@ -1,14 +1,14 @@
-name: Publish to Winget
-on:
-  release:
-    types: [released]
-
-jobs:
-  publish:
-    runs-on: ubuntu-latest
-    steps:
-      - uses: vedantmgoyal2009/winget-releaser@v2
-        with:
-          identifier: Rclone.Rclone
-          installers-regex: '-windows-\w+\.zip$'
-          token: ${{ secrets.WINGET_TOKEN }}
+name: Publish to Winget
+on:
+  release:
+    types: [released]
+
+jobs:
+  publish:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: vedantmgoyal2009/winget-releaser@v2
+        with:
+          identifier: Rclone.Rclone
+          installers-regex: '-windows-\w+\.zip$'
+          token: ${{ secrets.WINGET_TOKEN }}
diff --git a/backend/azureblob/azureblob.go b/backend/azureblob/azureblob.go
index 36bd50e30..9855170d2 100644
--- a/backend/azureblob/azureblob.go
+++ b/backend/azureblob/azureblob.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !solaris && !js
-// +build !plan9,!solaris,!js
 
 // Package azureblob provides an interface to the Microsoft Azure blob object storage system
 package azureblob
diff --git a/backend/azureblob/azureblob_unsupported.go b/backend/azureblob/azureblob_unsupported.go
index 369d6e367..b5ccf8643 100644
--- a/backend/azureblob/azureblob_unsupported.go
+++ b/backend/azureblob/azureblob_unsupported.go
@@ -2,6 +2,5 @@
 // about "no buildable Go source files "
 
 //go:build plan9 || solaris || js
-// +build plan9 solaris js
 
 package azureblob
diff --git a/backend/azurefiles/azurefiles.go b/backend/azurefiles/azurefiles.go
index 95275f6d7..06046f060 100644
--- a/backend/azurefiles/azurefiles.go
+++ b/backend/azurefiles/azurefiles.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !js
-// +build !plan9,!js
 
 // Package azurefiles provides an interface to Microsoft Azure Files
 package azurefiles
diff --git a/backend/azurefiles/azurefiles_unsupported.go b/backend/azurefiles/azurefiles_unsupported.go
index 1674e8f20..f261676fd 100644
--- a/backend/azurefiles/azurefiles_unsupported.go
+++ b/backend/azurefiles/azurefiles_unsupported.go
@@ -2,6 +2,5 @@
 // about "no buildable Go source files "
 
 //go:build plan9 || js
-// +build plan9 js
 
 package azurefiles
diff --git a/backend/cache/cache.go b/backend/cache/cache.go
index 828744c47..7ca097354 100644
--- a/backend/cache/cache.go
+++ b/backend/cache/cache.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !js
-// +build !plan9,!js
 
 // Package cache implements a virtual provider to cache existing remotes.
 package cache
diff --git a/backend/cache/cache_unsupported.go b/backend/cache/cache_unsupported.go
index a14a7beaa..8ce32ee66 100644
--- a/backend/cache/cache_unsupported.go
+++ b/backend/cache/cache_unsupported.go
@@ -2,6 +2,5 @@
 // about "no buildable Go source files "
 
 //go:build plan9 || js
-// +build plan9 js
 
 package cache
diff --git a/backend/cache/directory.go b/backend/cache/directory.go
index ab4ea9112..5c45db9c7 100644
--- a/backend/cache/directory.go
+++ b/backend/cache/directory.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !js
-// +build !plan9,!js
 
 package cache
 
diff --git a/backend/cache/handle.go b/backend/cache/handle.go
index df1029c46..a226fa5c4 100644
--- a/backend/cache/handle.go
+++ b/backend/cache/handle.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !js
-// +build !plan9,!js
 
 package cache
 
diff --git a/backend/cache/object.go b/backend/cache/object.go
index 8dc072017..87c292804 100644
--- a/backend/cache/object.go
+++ b/backend/cache/object.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !js
-// +build !plan9,!js
 
 package cache
 
diff --git a/backend/cache/plex.go b/backend/cache/plex.go
index 8d57ecb17..040a665ef 100644
--- a/backend/cache/plex.go
+++ b/backend/cache/plex.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !js
-// +build !plan9,!js
 
 package cache
 
diff --git a/backend/cache/storage_memory.go b/backend/cache/storage_memory.go
index 25ac3bb62..2b2acf8f4 100644
--- a/backend/cache/storage_memory.go
+++ b/backend/cache/storage_memory.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !js
-// +build !plan9,!js
 
 package cache
 
diff --git a/backend/cache/storage_persistent.go b/backend/cache/storage_persistent.go
index ac8fdfd57..590c50468 100644
--- a/backend/cache/storage_persistent.go
+++ b/backend/cache/storage_persistent.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !js
-// +build !plan9,!js
 
 package cache
 
diff --git a/backend/hdfs/fs.go b/backend/hdfs/fs.go
index cf2ee0e60..7a309d608 100644
--- a/backend/hdfs/fs.go
+++ b/backend/hdfs/fs.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 package hdfs
 
diff --git a/backend/hdfs/hdfs.go b/backend/hdfs/hdfs.go
index 312aa1e5c..87d85e633 100644
--- a/backend/hdfs/hdfs.go
+++ b/backend/hdfs/hdfs.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 // Package hdfs provides an interface to the HDFS storage system.
 package hdfs
diff --git a/backend/hdfs/hdfs_unsupported.go b/backend/hdfs/hdfs_unsupported.go
index afa686adb..02305691b 100644
--- a/backend/hdfs/hdfs_unsupported.go
+++ b/backend/hdfs/hdfs_unsupported.go
@@ -2,6 +2,5 @@
 // about "no buildable Go source files "
 
 //go:build plan9
-// +build plan9
 
 package hdfs
diff --git a/backend/hdfs/object.go b/backend/hdfs/object.go
index a2c2c1087..d6d25297f 100644
--- a/backend/hdfs/object.go
+++ b/backend/hdfs/object.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 package hdfs
 
diff --git a/backend/http/http.go b/backend/http/http.go
index 862376d4f..ce03bb9bd 100644
--- a/backend/http/http.go
+++ b/backend/http/http.go
@@ -89,6 +89,10 @@ that directory listings are much quicker, but rclone won't have the times or
 sizes of any files, and some files that don't exist may be in the listing.`,
 			Default:  false,
 			Advanced: true,
+		}, {
+			Name:    "no_escape",
+			Help:    "Do not escape URL metacharacters in path names.",
+			Default: false,
 		}},
 	}
 	fs.Register(fsi)
@@ -100,6 +104,7 @@ type Options struct {
 	NoSlash  bool            `config:"no_slash"`
 	NoHead   bool            `config:"no_head"`
 	Headers  fs.CommaSepList `config:"headers"`
+	NoEscape bool            `config:"no_escape"`
 }
 
 // Fs stores the interface to the remote HTTP files
@@ -326,6 +331,11 @@ func (f *Fs) NewObject(ctx context.Context, remote string) (fs.Object, error) {
 
 // Join's the remote onto the base URL
 func (f *Fs) url(remote string) string {
+	if f.opt.NoEscape {
+		// Directly concatenate without escaping, no_escape behavior
+		return f.endpointURL + remote
+	}
+	// Default behavior
 	return f.endpointURL + rest.URLPathEscape(remote)
 }
 
diff --git a/backend/local/about_unix.go b/backend/local/about_unix.go
index 86f28d74f..24134c794 100644
--- a/backend/local/about_unix.go
+++ b/backend/local/about_unix.go
@@ -1,5 +1,4 @@
 //go:build darwin || dragonfly || freebsd || linux
-// +build darwin dragonfly freebsd linux
 
 package local
 
diff --git a/backend/local/about_windows.go b/backend/local/about_windows.go
index f4fba6195..1d4ab338e 100644
--- a/backend/local/about_windows.go
+++ b/backend/local/about_windows.go
@@ -1,5 +1,4 @@
 //go:build windows
-// +build windows
 
 package local
 
diff --git a/backend/local/fadvise_other.go b/backend/local/fadvise_other.go
index 9bf2f6260..c07a7d01c 100644
--- a/backend/local/fadvise_other.go
+++ b/backend/local/fadvise_other.go
@@ -1,5 +1,4 @@
 //go:build !linux
-// +build !linux
 
 package local
 
diff --git a/backend/local/fadvise_unix.go b/backend/local/fadvise_unix.go
index 14bbb6b04..f463e017c 100644
--- a/backend/local/fadvise_unix.go
+++ b/backend/local/fadvise_unix.go
@@ -1,5 +1,4 @@
 //go:build linux
-// +build linux
 
 package local
 
diff --git a/backend/local/lchtimes.go b/backend/local/lchtimes.go
index 97f3b1be1..c8f03ef46 100644
--- a/backend/local/lchtimes.go
+++ b/backend/local/lchtimes.go
@@ -1,5 +1,4 @@
 //go:build windows || plan9 || js
-// +build windows plan9 js
 
 package local
 
diff --git a/backend/local/lchtimes_unix.go b/backend/local/lchtimes_unix.go
index 478829159..96889db47 100644
--- a/backend/local/lchtimes_unix.go
+++ b/backend/local/lchtimes_unix.go
@@ -1,5 +1,4 @@
 //go:build !windows && !plan9 && !js
-// +build !windows,!plan9,!js
 
 package local
 
diff --git a/backend/local/metadata_bsd.go b/backend/local/metadata_bsd.go
index 87c18fc3e..cd5976eaa 100644
--- a/backend/local/metadata_bsd.go
+++ b/backend/local/metadata_bsd.go
@@ -1,5 +1,4 @@
 //go:build darwin || freebsd || netbsd
-// +build darwin freebsd netbsd
 
 package local
 
diff --git a/backend/local/metadata_linux.go b/backend/local/metadata_linux.go
index 261fcdbd0..dc0b1d233 100644
--- a/backend/local/metadata_linux.go
+++ b/backend/local/metadata_linux.go
@@ -1,5 +1,4 @@
 //go:build linux
-// +build linux
 
 package local
 
diff --git a/backend/local/metadata_other.go b/backend/local/metadata_other.go
index 154ecd8b5..c32c89f26 100644
--- a/backend/local/metadata_other.go
+++ b/backend/local/metadata_other.go
@@ -1,5 +1,4 @@
 //go:build plan9 || js
-// +build plan9 js
 
 package local
 
diff --git a/backend/local/metadata_unix.go b/backend/local/metadata_unix.go
index dd7e26ecf..d1695ad7c 100644
--- a/backend/local/metadata_unix.go
+++ b/backend/local/metadata_unix.go
@@ -1,5 +1,4 @@
 //go:build openbsd || solaris
-// +build openbsd solaris
 
 package local
 
diff --git a/backend/local/metadata_windows.go b/backend/local/metadata_windows.go
index d74c3f51e..00fad75ba 100644
--- a/backend/local/metadata_windows.go
+++ b/backend/local/metadata_windows.go
@@ -1,5 +1,4 @@
 //go:build windows
-// +build windows
 
 package local
 
diff --git a/backend/local/read_device_other.go b/backend/local/read_device_other.go
index a5a455d0c..3455ab346 100644
--- a/backend/local/read_device_other.go
+++ b/backend/local/read_device_other.go
@@ -1,7 +1,6 @@
 // Device reading functions
 
 //go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris
-// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
 
 package local
 
diff --git a/backend/local/read_device_unix.go b/backend/local/read_device_unix.go
index 3297194b3..ab7fecbee 100644
--- a/backend/local/read_device_unix.go
+++ b/backend/local/read_device_unix.go
@@ -1,7 +1,6 @@
 // Device reading functions
 
 //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
 
 package local
 
diff --git a/backend/local/remove_other.go b/backend/local/remove_other.go
index b0deeeec8..25a19eedf 100644
--- a/backend/local/remove_other.go
+++ b/backend/local/remove_other.go
@@ -1,5 +1,4 @@
 //go:build !windows
-// +build !windows
 
 package local
 
diff --git a/backend/local/remove_windows.go b/backend/local/remove_windows.go
index 989c75805..a04f4af66 100644
--- a/backend/local/remove_windows.go
+++ b/backend/local/remove_windows.go
@@ -1,5 +1,4 @@
 //go:build windows
-// +build windows
 
 package local
 
diff --git a/backend/local/setbtime.go b/backend/local/setbtime.go
index 5d2c462ee..5c946348f 100644
--- a/backend/local/setbtime.go
+++ b/backend/local/setbtime.go
@@ -1,5 +1,4 @@
 //go:build !windows
-// +build !windows
 
 package local
 
diff --git a/backend/local/setbtime_windows.go b/backend/local/setbtime_windows.go
index 2a46f09eb..510a4da6a 100644
--- a/backend/local/setbtime_windows.go
+++ b/backend/local/setbtime_windows.go
@@ -1,5 +1,4 @@
 //go:build windows
-// +build windows
 
 package local
 
diff --git a/backend/local/symlink.go b/backend/local/symlink.go
index c55fb50a2..bdce264c7 100644
--- a/backend/local/symlink.go
+++ b/backend/local/symlink.go
@@ -1,5 +1,4 @@
 //go:build !windows && !plan9 && !js
-// +build !windows,!plan9,!js
 
 package local
 
diff --git a/backend/local/symlink_other.go b/backend/local/symlink_other.go
index 2b942c6fc..2d5bcab07 100644
--- a/backend/local/symlink_other.go
+++ b/backend/local/symlink_other.go
@@ -1,5 +1,4 @@
 //go:build windows || plan9 || js
-// +build windows plan9 js
 
 package local
 
diff --git a/backend/local/xattr.go b/backend/local/xattr.go
index fec0e4e7b..e34dc02ad 100644
--- a/backend/local/xattr.go
+++ b/backend/local/xattr.go
@@ -1,5 +1,4 @@
 //go:build !openbsd && !plan9
-// +build !openbsd,!plan9
 
 package local
 
diff --git a/backend/local/xattr_unsupported.go b/backend/local/xattr_unsupported.go
index 88455939a..e63c25492 100644
--- a/backend/local/xattr_unsupported.go
+++ b/backend/local/xattr_unsupported.go
@@ -1,5 +1,4 @@
 //go:build openbsd || plan9
-// +build openbsd plan9
 
 // The pkg/xattr module doesn't compile for openbsd or plan9
 package local
diff --git a/backend/oracleobjectstorage/byok.go b/backend/oracleobjectstorage/byok.go
index 450705d1d..85daa158d 100644
--- a/backend/oracleobjectstorage/byok.go
+++ b/backend/oracleobjectstorage/byok.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !solaris && !js
-// +build !plan9,!solaris,!js
 
 package oracleobjectstorage
 
diff --git a/backend/oracleobjectstorage/client.go b/backend/oracleobjectstorage/client.go
index ae2e8635c..0749c4699 100644
--- a/backend/oracleobjectstorage/client.go
+++ b/backend/oracleobjectstorage/client.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !solaris && !js
-// +build !plan9,!solaris,!js
 
 package oracleobjectstorage
 
diff --git a/backend/oracleobjectstorage/command.go b/backend/oracleobjectstorage/command.go
index e6b079231..13c288caa 100644
--- a/backend/oracleobjectstorage/command.go
+++ b/backend/oracleobjectstorage/command.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !solaris && !js
-// +build !plan9,!solaris,!js
 
 package oracleobjectstorage
 
diff --git a/backend/oracleobjectstorage/copy.go b/backend/oracleobjectstorage/copy.go
index fec418fbd..06fed4c7a 100644
--- a/backend/oracleobjectstorage/copy.go
+++ b/backend/oracleobjectstorage/copy.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !solaris && !js
-// +build !plan9,!solaris,!js
 
 package oracleobjectstorage
 
diff --git a/backend/oracleobjectstorage/multipart.go b/backend/oracleobjectstorage/multipart.go
index 93c7a9c3d..7ecdf16bd 100644
--- a/backend/oracleobjectstorage/multipart.go
+++ b/backend/oracleobjectstorage/multipart.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !solaris && !js
-// +build !plan9,!solaris,!js
 
 package oracleobjectstorage
 
diff --git a/backend/oracleobjectstorage/object.go b/backend/oracleobjectstorage/object.go
index ad390eaa0..834ec66c5 100644
--- a/backend/oracleobjectstorage/object.go
+++ b/backend/oracleobjectstorage/object.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !solaris && !js
-// +build !plan9,!solaris,!js
 
 package oracleobjectstorage
 
diff --git a/backend/oracleobjectstorage/options.go b/backend/oracleobjectstorage/options.go
index 3fb1e4b6c..323a61699 100644
--- a/backend/oracleobjectstorage/options.go
+++ b/backend/oracleobjectstorage/options.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !solaris && !js
-// +build !plan9,!solaris,!js
 
 package oracleobjectstorage
 
diff --git a/backend/oracleobjectstorage/oracleobjectstorage.go b/backend/oracleobjectstorage/oracleobjectstorage.go
index 2133ebc09..a4d0f00fa 100644
--- a/backend/oracleobjectstorage/oracleobjectstorage.go
+++ b/backend/oracleobjectstorage/oracleobjectstorage.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !solaris && !js
-// +build !plan9,!solaris,!js
 
 // Package oracleobjectstorage provides an interface to the OCI object storage system.
 package oracleobjectstorage
diff --git a/backend/oracleobjectstorage/oracleobjectstorage_unsupported.go b/backend/oracleobjectstorage/oracleobjectstorage_unsupported.go
index 8df06ee6a..07d8fd242 100644
--- a/backend/oracleobjectstorage/oracleobjectstorage_unsupported.go
+++ b/backend/oracleobjectstorage/oracleobjectstorage_unsupported.go
@@ -2,6 +2,5 @@
 // about "no buildable Go source files "
 
 //go:build plan9 || solaris || js
-// +build plan9 solaris js
 
 package oracleobjectstorage
diff --git a/backend/oracleobjectstorage/waiter.go b/backend/oracleobjectstorage/waiter.go
index d241ff8a7..9981a1ebd 100644
--- a/backend/oracleobjectstorage/waiter.go
+++ b/backend/oracleobjectstorage/waiter.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !solaris && !js
-// +build !plan9,!solaris,!js
 
 package oracleobjectstorage
 
diff --git a/backend/qingstor/qingstor.go b/backend/qingstor/qingstor.go
index 9f3a2a016..3dfa36b15 100644
--- a/backend/qingstor/qingstor.go
+++ b/backend/qingstor/qingstor.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !js
-// +build !plan9,!js
 
 // Package qingstor provides an interface to QingStor object storage
 // Home: https://www.qingcloud.com/
diff --git a/backend/qingstor/qingstor_unsupported.go b/backend/qingstor/qingstor_unsupported.go
index 4f453acef..209d909bc 100644
--- a/backend/qingstor/qingstor_unsupported.go
+++ b/backend/qingstor/qingstor_unsupported.go
@@ -2,6 +2,5 @@
 // about "no buildable Go source files "
 
 //go:build plan9 || js
-// +build plan9 js
 
 package qingstor
diff --git a/backend/qingstor/upload.go b/backend/qingstor/upload.go
index 797e718f8..f0029f674 100644
--- a/backend/qingstor/upload.go
+++ b/backend/qingstor/upload.go
@@ -1,7 +1,6 @@
 // Upload object to QingStor
 
 //go:build !plan9 && !js
-// +build !plan9,!js
 
 package qingstor
 
diff --git a/backend/s3/gen_setfrom.go b/backend/s3/gen_setfrom.go
index b70615283..9dd037086 100644
--- a/backend/s3/gen_setfrom.go
+++ b/backend/s3/gen_setfrom.go
@@ -1,7 +1,6 @@
 // Generate boilerplate code for setting similar structs from each other
 
 //go:build ignore
-// +build ignore
 
 package main
 
diff --git a/backend/sftp/sftp.go b/backend/sftp/sftp.go
index 97e8ca4a6..474163866 100644
--- a/backend/sftp/sftp.go
+++ b/backend/sftp/sftp.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 // Package sftp provides a filesystem interface using github.com/pkg/sftp
 package sftp
diff --git a/backend/sftp/sftp_unsupported.go b/backend/sftp/sftp_unsupported.go
index 27f4cc9f5..8dc950374 100644
--- a/backend/sftp/sftp_unsupported.go
+++ b/backend/sftp/sftp_unsupported.go
@@ -2,6 +2,5 @@
 // about "no buildable Go source files "
 
 //go:build plan9
-// +build plan9
 
 package sftp
diff --git a/backend/sftp/ssh.go b/backend/sftp/ssh.go
index 4c6e65aca..d0a25e29e 100644
--- a/backend/sftp/ssh.go
+++ b/backend/sftp/ssh.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 package sftp
 
diff --git a/backend/sftp/ssh_external.go b/backend/sftp/ssh_external.go
index bbea27ea8..6c52acd8f 100644
--- a/backend/sftp/ssh_external.go
+++ b/backend/sftp/ssh_external.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 package sftp
 
diff --git a/backend/sftp/ssh_internal.go b/backend/sftp/ssh_internal.go
index 2352601e3..8911cc13c 100644
--- a/backend/sftp/ssh_internal.go
+++ b/backend/sftp/ssh_internal.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 package sftp
 
diff --git a/backend/sftp/stringlock.go b/backend/sftp/stringlock.go
index a5167a7da..df658f961 100644
--- a/backend/sftp/stringlock.go
+++ b/backend/sftp/stringlock.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 package sftp
 
diff --git a/backend/sharefile/generate_tzdata.go b/backend/sharefile/generate_tzdata.go
index 1e01a720a..90cb32bd5 100644
--- a/backend/sharefile/generate_tzdata.go
+++ b/backend/sharefile/generate_tzdata.go
@@ -1,5 +1,4 @@
 //go:build ignore
-// +build ignore
 
 package main
 
diff --git a/backend/storj/fs.go b/backend/storj/fs.go
index 1200c40d6..84be8bc68 100644
--- a/backend/storj/fs.go
+++ b/backend/storj/fs.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 // Package storj provides an interface to Storj decentralized object storage.
 package storj
diff --git a/backend/storj/object.go b/backend/storj/object.go
index ea85026af..479d54a5a 100644
--- a/backend/storj/object.go
+++ b/backend/storj/object.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 package storj
 
diff --git a/backend/storj/storj_unsupported.go b/backend/storj/storj_unsupported.go
index 9f044ddd4..67f9ebdfd 100644
--- a/backend/storj/storj_unsupported.go
+++ b/backend/storj/storj_unsupported.go
@@ -1,4 +1,3 @@
 //go:build plan9
-// +build plan9
 
 package storj
diff --git a/bin/check-merged.go b/bin/check-merged.go
index 986a60ec1..0132f1263 100644
--- a/bin/check-merged.go
+++ b/bin/check-merged.go
@@ -1,5 +1,4 @@
 //go:build ignore
-// +build ignore
 
 // Attempt to work out if branches have already been merged
 package main
diff --git a/bin/cross-compile.go b/bin/cross-compile.go
index f0a02336f..a89bac327 100644
--- a/bin/cross-compile.go
+++ b/bin/cross-compile.go
@@ -1,5 +1,4 @@
 //go:build ignore
-// +build ignore
 
 // Cross compile rclone - in go because I hate bash ;-)
 
diff --git a/bin/get-github-release.go b/bin/get-github-release.go
index 3aa97cd36..64a256b90 100644
--- a/bin/get-github-release.go
+++ b/bin/get-github-release.go
@@ -1,5 +1,4 @@
 //go:build ignore
-// +build ignore
 
 // Get the latest release from a github project
 //
diff --git a/bin/resource_windows.go b/bin/resource_windows.go
index 2f74ad363..fab7dcafc 100644
--- a/bin/resource_windows.go
+++ b/bin/resource_windows.go
@@ -16,7 +16,6 @@
 
 //go:generate go run resource_windows.go
 //go:build tools
-// +build tools
 
 package main
 
diff --git a/cmd/cachestats/cachestats.go b/cmd/cachestats/cachestats.go
index f5cbf0095..f9c664bfa 100644
--- a/cmd/cachestats/cachestats.go
+++ b/cmd/cachestats/cachestats.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !js
-// +build !plan9,!js
 
 // Package cachestats provides the cachestats command.
 package cachestats
diff --git a/cmd/cachestats/cachestats_unsupported.go b/cmd/cachestats/cachestats_unsupported.go
index 6e2987722..089ba751a 100644
--- a/cmd/cachestats/cachestats_unsupported.go
+++ b/cmd/cachestats/cachestats_unsupported.go
@@ -2,6 +2,5 @@
 // about "no buildable Go source files "
 
 //go:build plan9 || js
-// +build plan9 js
 
 package cachestats
diff --git a/cmd/cmount/fs.go b/cmd/cmount/fs.go
index ea66e3bd6..7466eee85 100644
--- a/cmd/cmount/fs.go
+++ b/cmd/cmount/fs.go
@@ -1,6 +1,4 @@
 //go:build cmount && ((linux && cgo) || (darwin && cgo) || (freebsd && cgo) || windows)
-// +build cmount
-// +build linux,cgo darwin,cgo freebsd,cgo windows
 
 package cmount
 
diff --git a/cmd/cmount/mount.go b/cmd/cmount/mount.go
index 583a48427..56e61fe18 100644
--- a/cmd/cmount/mount.go
+++ b/cmd/cmount/mount.go
@@ -1,6 +1,4 @@
 //go:build cmount && ((linux && cgo) || (darwin && cgo) || (freebsd && cgo) || windows)
-// +build cmount
-// +build linux,cgo darwin,cgo freebsd,cgo windows
 
 // Package cmount implements a FUSE mounting system for rclone remotes.
 //
diff --git a/cmd/cmount/mount_brew.go b/cmd/cmount/mount_brew.go
index 7f368ccab..9a837de7f 100644
--- a/cmd/cmount/mount_brew.go
+++ b/cmd/cmount/mount_brew.go
@@ -1,5 +1,4 @@
 //go:build brew && darwin
-// +build brew,darwin
 
 // Package cmount implements a FUSE mounting system for rclone remotes.
 //
diff --git a/cmd/cmount/mount_unsupported.go b/cmd/cmount/mount_unsupported.go
index 375cec456..6677132d7 100644
--- a/cmd/cmount/mount_unsupported.go
+++ b/cmd/cmount/mount_unsupported.go
@@ -1,8 +1,4 @@
 //go:build !((linux && cgo && cmount) || (darwin && cgo && cmount) || (freebsd && cgo && cmount) || (windows && cmount))
-// +build !linux !cgo !cmount
-// +build !darwin !cgo !cmount
-// +build !freebsd !cgo !cmount
-// +build !windows !cmount
 
 // Package cmount implements a FUSE mounting system for rclone remotes.
 //
diff --git a/cmd/cmount/mountpoint_other.go b/cmd/cmount/mountpoint_other.go
index 0e69487d1..e1dc66e2c 100644
--- a/cmd/cmount/mountpoint_other.go
+++ b/cmd/cmount/mountpoint_other.go
@@ -1,5 +1,4 @@
 //go:build cmount && cgo && !windows
-// +build cmount,cgo,!windows
 
 package cmount
 
diff --git a/cmd/cmount/mountpoint_windows.go b/cmd/cmount/mountpoint_windows.go
index 0445187c7..ee7a3bebd 100644
--- a/cmd/cmount/mountpoint_windows.go
+++ b/cmd/cmount/mountpoint_windows.go
@@ -1,5 +1,4 @@
 //go:build cmount && windows
-// +build cmount,windows
 
 package cmount
 
diff --git a/cmd/mount/dir.go b/cmd/mount/dir.go
index 4a6f939f6..c044fcff3 100644
--- a/cmd/mount/dir.go
+++ b/cmd/mount/dir.go
@@ -1,5 +1,4 @@
 //go:build linux
-// +build linux
 
 package mount
 
diff --git a/cmd/mount/file.go b/cmd/mount/file.go
index a660bcafa..da0897fb8 100644
--- a/cmd/mount/file.go
+++ b/cmd/mount/file.go
@@ -1,5 +1,4 @@
 //go:build linux
-// +build linux
 
 package mount
 
diff --git a/cmd/mount/fs.go b/cmd/mount/fs.go
index e81b2f078..66029bff0 100644
--- a/cmd/mount/fs.go
+++ b/cmd/mount/fs.go
@@ -1,7 +1,6 @@
 // FUSE main Fs
 
 //go:build linux
-// +build linux
 
 package mount
 
diff --git a/cmd/mount/handle.go b/cmd/mount/handle.go
index 65d344538..94f8214c7 100644
--- a/cmd/mount/handle.go
+++ b/cmd/mount/handle.go
@@ -1,5 +1,4 @@
 //go:build linux
-// +build linux
 
 package mount
 
diff --git a/cmd/mount/mount.go b/cmd/mount/mount.go
index b32ba29ae..4fa832b57 100644
--- a/cmd/mount/mount.go
+++ b/cmd/mount/mount.go
@@ -1,5 +1,4 @@
 //go:build linux
-// +build linux
 
 // Package mount implements a FUSE mounting system for rclone remotes.
 package mount
diff --git a/cmd/mount/mount_unsupported.go b/cmd/mount/mount_unsupported.go
index c2feafbc3..d896768cd 100644
--- a/cmd/mount/mount_unsupported.go
+++ b/cmd/mount/mount_unsupported.go
@@ -1,5 +1,4 @@
 //go:build !linux
-// +build !linux
 
 // Package mount implements a FUSE mounting system for rclone remotes.
 //
diff --git a/cmd/mount2/file.go b/cmd/mount2/file.go
index 8d6b9b968..5e225e4e4 100644
--- a/cmd/mount2/file.go
+++ b/cmd/mount2/file.go
@@ -1,5 +1,4 @@
 //go:build linux || (darwin && amd64)
-// +build linux darwin,amd64
 
 package mount2
 
diff --git a/cmd/mount2/fs.go b/cmd/mount2/fs.go
index 0ab28f05a..8ede62af1 100644
--- a/cmd/mount2/fs.go
+++ b/cmd/mount2/fs.go
@@ -1,7 +1,6 @@
 // FUSE main Fs
 
 //go:build linux || (darwin && amd64)
-// +build linux darwin,amd64
 
 package mount2
 
diff --git a/cmd/mount2/mount.go b/cmd/mount2/mount.go
index f244bf40d..7eee41057 100644
--- a/cmd/mount2/mount.go
+++ b/cmd/mount2/mount.go
@@ -1,5 +1,4 @@
 //go:build linux || (darwin && amd64)
-// +build linux darwin,amd64
 
 // Package mount2 implements a FUSE mounting system for rclone remotes.
 package mount2
diff --git a/cmd/mount2/mount_unsupported.go b/cmd/mount2/mount_unsupported.go
index 649eab0a2..ab8c5bd0a 100644
--- a/cmd/mount2/mount_unsupported.go
+++ b/cmd/mount2/mount_unsupported.go
@@ -1,6 +1,4 @@
 //go:build !linux && (!darwin || !amd64)
-// +build !linux
-// +build !darwin !amd64
 
 // Package mount2 implements a FUSE mounting system for rclone remotes.
 //
diff --git a/cmd/mount2/node.go b/cmd/mount2/node.go
index ee830b51b..7544040b8 100644
--- a/cmd/mount2/node.go
+++ b/cmd/mount2/node.go
@@ -1,5 +1,4 @@
 //go:build linux || (darwin && amd64)
-// +build linux darwin,amd64
 
 package mount2
 
diff --git a/cmd/mountlib/check_linux.go b/cmd/mountlib/check_linux.go
index 58d839bf5..81c144ee3 100644
--- a/cmd/mountlib/check_linux.go
+++ b/cmd/mountlib/check_linux.go
@@ -1,5 +1,4 @@
 //go:build linux
-// +build linux
 
 package mountlib
 
diff --git a/cmd/mountlib/check_other.go b/cmd/mountlib/check_other.go
index 760be4ec6..82cf5f2fb 100644
--- a/cmd/mountlib/check_other.go
+++ b/cmd/mountlib/check_other.go
@@ -1,5 +1,4 @@
 //go:build !linux
-// +build !linux
 
 package mountlib
 
diff --git a/cmd/mountlib/sighup.go b/cmd/mountlib/sighup.go
index 7b661a2db..2dfbf9621 100644
--- a/cmd/mountlib/sighup.go
+++ b/cmd/mountlib/sighup.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !js
-// +build !plan9,!js
 
 package mountlib
 
diff --git a/cmd/mountlib/sighup_unsupported.go b/cmd/mountlib/sighup_unsupported.go
index b9c80895b..8e786f696 100644
--- a/cmd/mountlib/sighup_unsupported.go
+++ b/cmd/mountlib/sighup_unsupported.go
@@ -1,5 +1,4 @@
 //go:build plan9 || js
-// +build plan9 js
 
 package mountlib
 
diff --git a/cmd/ncdu/ncdu.go b/cmd/ncdu/ncdu.go
index dbbc146e5..a1e535ba2 100644
--- a/cmd/ncdu/ncdu.go
+++ b/cmd/ncdu/ncdu.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !js
-// +build !plan9,!js
 
 // Package ncdu implements a text based user interface for exploring a remote
 package ncdu
diff --git a/cmd/ncdu/ncdu_unsupported.go b/cmd/ncdu/ncdu_unsupported.go
index b4a9b22cf..e1f6430c2 100644
--- a/cmd/ncdu/ncdu_unsupported.go
+++ b/cmd/ncdu/ncdu_unsupported.go
@@ -2,6 +2,5 @@
 // about "no buildable Go source files "
 
 //go:build plan9 || js
-// +build plan9 js
 
 package ncdu
diff --git a/cmd/nfsmount/nfsmount.go b/cmd/nfsmount/nfsmount.go
index 8a1fdea2e..08fc20fd7 100644
--- a/cmd/nfsmount/nfsmount.go
+++ b/cmd/nfsmount/nfsmount.go
@@ -1,5 +1,4 @@
 //go:build unix
-// +build unix
 
 // Package nfsmount implements mounting functionality using serve nfs command
 //
diff --git a/cmd/nfsmount/nfsmount_unsupported.go b/cmd/nfsmount/nfsmount_unsupported.go
index 394374e66..7ff9f1aac 100644
--- a/cmd/nfsmount/nfsmount_unsupported.go
+++ b/cmd/nfsmount/nfsmount_unsupported.go
@@ -2,7 +2,6 @@
 // about "no buildable Go source files "
 
 //go:build !unix
-// +build !unix
 
 // Package nfsmount implements mount command using NFS.
 package nfsmount
diff --git a/cmd/selfupdate/noselfupdate.go b/cmd/selfupdate/noselfupdate.go
index 05e5ad120..332353681 100644
--- a/cmd/selfupdate/noselfupdate.go
+++ b/cmd/selfupdate/noselfupdate.go
@@ -1,5 +1,4 @@
 //go:build noselfupdate
-// +build noselfupdate
 
 package selfupdate
 
diff --git a/cmd/selfupdate/selfupdate.go b/cmd/selfupdate/selfupdate.go
index 5adf9a4b8..6e0b61e8d 100644
--- a/cmd/selfupdate/selfupdate.go
+++ b/cmd/selfupdate/selfupdate.go
@@ -1,5 +1,4 @@
 //go:build !noselfupdate
-// +build !noselfupdate
 
 // Package selfupdate provides the selfupdate command.
 package selfupdate
diff --git a/cmd/selfupdate/verify.go b/cmd/selfupdate/verify.go
index 7c3d76df6..78ba46f3b 100644
--- a/cmd/selfupdate/verify.go
+++ b/cmd/selfupdate/verify.go
@@ -1,5 +1,4 @@
 //go:build !noselfupdate
-// +build !noselfupdate
 
 package selfupdate
 
diff --git a/cmd/selfupdate/writable_unix.go b/cmd/selfupdate/writable_unix.go
index 020f75492..48c355717 100644
--- a/cmd/selfupdate/writable_unix.go
+++ b/cmd/selfupdate/writable_unix.go
@@ -1,5 +1,4 @@
 //go:build !windows && !plan9 && !js && !noselfupdate
-// +build !windows,!plan9,!js,!noselfupdate
 
 package selfupdate
 
diff --git a/cmd/selfupdate/writable_unsupported.go b/cmd/selfupdate/writable_unsupported.go
index 4944e7b46..0f0380c01 100644
--- a/cmd/selfupdate/writable_unsupported.go
+++ b/cmd/selfupdate/writable_unsupported.go
@@ -1,6 +1,4 @@
 //go:build (plan9 || js) && !noselfupdate
-// +build plan9 js
-// +build !noselfupdate
 
 package selfupdate
 
diff --git a/cmd/selfupdate/writable_windows.go b/cmd/selfupdate/writable_windows.go
index eed74b32a..6699975e6 100644
--- a/cmd/selfupdate/writable_windows.go
+++ b/cmd/selfupdate/writable_windows.go
@@ -1,5 +1,4 @@
 //go:build windows && !noselfupdate
-// +build windows,!noselfupdate
 
 package selfupdate
 
diff --git a/cmd/selfupdate_disabled.go b/cmd/selfupdate_disabled.go
index 3daf1c88d..f80078761 100644
--- a/cmd/selfupdate_disabled.go
+++ b/cmd/selfupdate_disabled.go
@@ -1,5 +1,4 @@
 //go:build noselfupdate
-// +build noselfupdate
 
 package cmd
 
diff --git a/cmd/selfupdate_enabled.go b/cmd/selfupdate_enabled.go
index 41aa5f125..bc636aa11 100644
--- a/cmd/selfupdate_enabled.go
+++ b/cmd/selfupdate_enabled.go
@@ -1,5 +1,4 @@
 //go:build !noselfupdate
-// +build !noselfupdate
 
 package cmd
 
diff --git a/cmd/serve/dlna/data/assets_generate.go b/cmd/serve/dlna/data/assets_generate.go
index 69230a297..015ca45a8 100644
--- a/cmd/serve/dlna/data/assets_generate.go
+++ b/cmd/serve/dlna/data/assets_generate.go
@@ -1,7 +1,6 @@
 //go:generate go run assets_generate.go
 // The "go:generate" directive compiles static assets by running assets_generate.go
 //go:build ignore
-// +build ignore
 
 package main
 
diff --git a/cmd/serve/docker/systemd.go b/cmd/serve/docker/systemd.go
index 8a69f6b08..0294d7786 100644
--- a/cmd/serve/docker/systemd.go
+++ b/cmd/serve/docker/systemd.go
@@ -1,5 +1,4 @@
 //go:build linux && !android
-// +build linux,!android
 
 package docker
 
diff --git a/cmd/serve/docker/systemd_unsupported.go b/cmd/serve/docker/systemd_unsupported.go
index 02b0b81a4..d11ad52d8 100644
--- a/cmd/serve/docker/systemd_unsupported.go
+++ b/cmd/serve/docker/systemd_unsupported.go
@@ -1,5 +1,4 @@
 //go:build !linux || android
-// +build !linux android
 
 package docker
 
diff --git a/cmd/serve/docker/unix.go b/cmd/serve/docker/unix.go
index 8bf7b6fbc..4b5da70ba 100644
--- a/cmd/serve/docker/unix.go
+++ b/cmd/serve/docker/unix.go
@@ -1,5 +1,4 @@
 //go:build linux || freebsd
-// +build linux freebsd
 
 package docker
 
diff --git a/cmd/serve/docker/unix_unsupported.go b/cmd/serve/docker/unix_unsupported.go
index 82ef12410..6adc26065 100644
--- a/cmd/serve/docker/unix_unsupported.go
+++ b/cmd/serve/docker/unix_unsupported.go
@@ -1,5 +1,4 @@
 //go:build !linux && !freebsd
-// +build !linux,!freebsd
 
 package docker
 
diff --git a/cmd/serve/ftp/ftp.go b/cmd/serve/ftp/ftp.go
index a07386305..d9b2ea607 100644
--- a/cmd/serve/ftp/ftp.go
+++ b/cmd/serve/ftp/ftp.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 // Package ftp implements an FTP server for rclone
 package ftp
diff --git a/cmd/serve/ftp/ftp_unsupported.go b/cmd/serve/ftp/ftp_unsupported.go
index 05ad78a39..7fa857560 100644
--- a/cmd/serve/ftp/ftp_unsupported.go
+++ b/cmd/serve/ftp/ftp_unsupported.go
@@ -2,7 +2,6 @@
 // about "no buildable Go source files "
 
 //go:build plan9
-// +build plan9
 
 package ftp
 
diff --git a/cmd/serve/nfs/filesystem.go b/cmd/serve/nfs/filesystem.go
index 9d3db34d9..cf058ee71 100644
--- a/cmd/serve/nfs/filesystem.go
+++ b/cmd/serve/nfs/filesystem.go
@@ -1,5 +1,4 @@
 //go:build unix
-// +build unix
 
 package nfs
 
diff --git a/cmd/serve/nfs/handler.go b/cmd/serve/nfs/handler.go
index ed00639af..313c83def 100644
--- a/cmd/serve/nfs/handler.go
+++ b/cmd/serve/nfs/handler.go
@@ -1,5 +1,4 @@
 //go:build unix
-// +build unix
 
 package nfs
 
diff --git a/cmd/serve/nfs/nfs.go b/cmd/serve/nfs/nfs.go
index b35931dec..69b571751 100644
--- a/cmd/serve/nfs/nfs.go
+++ b/cmd/serve/nfs/nfs.go
@@ -1,5 +1,4 @@
 //go:build unix
-// +build unix
 
 // Package nfs implements a server to serve a VFS remote over NFSv3 protocol
 //
diff --git a/cmd/serve/nfs/nfs_unsupported.go b/cmd/serve/nfs/nfs_unsupported.go
index 99b2f6df6..a438c9748 100644
--- a/cmd/serve/nfs/nfs_unsupported.go
+++ b/cmd/serve/nfs/nfs_unsupported.go
@@ -1,6 +1,5 @@
 // For unsupported architectures
 //go:build !unix
-// +build !unix
 
 // Package nfs is not supported on non-Unix platforms
 package nfs
diff --git a/cmd/serve/nfs/server.go b/cmd/serve/nfs/server.go
index 14e125264..a78793492 100644
--- a/cmd/serve/nfs/server.go
+++ b/cmd/serve/nfs/server.go
@@ -1,5 +1,4 @@
 //go:build unix
-// +build unix
 
 package nfs
 
diff --git a/cmd/serve/proxy/proxy_code.go b/cmd/serve/proxy/proxy_code.go
index 3b7b698b5..cc703e209 100644
--- a/cmd/serve/proxy/proxy_code.go
+++ b/cmd/serve/proxy/proxy_code.go
@@ -1,5 +1,4 @@
 //go:build ignore
-// +build ignore
 
 // A simple auth proxy for testing purposes
 package main
diff --git a/cmd/serve/sftp/connection.go b/cmd/serve/sftp/connection.go
index 91c83002c..ae52ccfbd 100644
--- a/cmd/serve/sftp/connection.go
+++ b/cmd/serve/sftp/connection.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 package sftp
 
diff --git a/cmd/serve/sftp/handler.go b/cmd/serve/sftp/handler.go
index b937af80a..f7c9c3c47 100644
--- a/cmd/serve/sftp/handler.go
+++ b/cmd/serve/sftp/handler.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 package sftp
 
diff --git a/cmd/serve/sftp/server.go b/cmd/serve/sftp/server.go
index b094ad48f..43944d4a0 100644
--- a/cmd/serve/sftp/server.go
+++ b/cmd/serve/sftp/server.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 package sftp
 
diff --git a/cmd/serve/sftp/sftp.go b/cmd/serve/sftp/sftp.go
index 495de5157..6ebd6d03f 100644
--- a/cmd/serve/sftp/sftp.go
+++ b/cmd/serve/sftp/sftp.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 // Package sftp implements an SFTP server to serve an rclone VFS
 package sftp
diff --git a/cmd/serve/sftp/sftp_unsupported.go b/cmd/serve/sftp/sftp_unsupported.go
index db3d265b5..9f0df6499 100644
--- a/cmd/serve/sftp/sftp_unsupported.go
+++ b/cmd/serve/sftp/sftp_unsupported.go
@@ -2,7 +2,6 @@
 // about "no buildable Go source files "
 
 //go:build plan9
-// +build plan9
 
 package sftp
 
diff --git a/cmd/siginfo_bsd.go b/cmd/siginfo_bsd.go
index fc4063913..2f5798f53 100644
--- a/cmd/siginfo_bsd.go
+++ b/cmd/siginfo_bsd.go
@@ -1,5 +1,4 @@
 //go:build darwin || freebsd || netbsd || dragonfly || openbsd
-// +build darwin freebsd netbsd dragonfly openbsd
 
 package cmd
 
diff --git a/cmd/siginfo_others.go b/cmd/siginfo_others.go
index 680dba1b5..da71babd9 100644
--- a/cmd/siginfo_others.go
+++ b/cmd/siginfo_others.go
@@ -1,5 +1,4 @@
 //go:build !darwin && !freebsd && !netbsd && !dragonfly && !openbsd
-// +build !darwin,!freebsd,!netbsd,!dragonfly,!openbsd
 
 package cmd
 
diff --git a/fs/accounting/accounting_other.go b/fs/accounting/accounting_other.go
index 3dc7f2843..dc05b95dc 100644
--- a/fs/accounting/accounting_other.go
+++ b/fs/accounting/accounting_other.go
@@ -2,7 +2,6 @@
 // Non-unix specific functions.
 
 //go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris
-// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
 
 package accounting
 
diff --git a/fs/accounting/accounting_unix.go b/fs/accounting/accounting_unix.go
index 761466a55..76c0a3509 100644
--- a/fs/accounting/accounting_unix.go
+++ b/fs/accounting/accounting_unix.go
@@ -2,7 +2,6 @@
 // Unix specific functions.
 
 //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
 
 package accounting
 
diff --git a/fs/accounting/stats.go b/fs/accounting/stats.go
index 393b6711a..7763c1497 100644
--- a/fs/accounting/stats.go
+++ b/fs/accounting/stats.go
@@ -464,7 +464,7 @@ func (s *StatsInfo) String() string {
 				s.checks, ts.totalChecks, percent(s.checks, ts.totalChecks))
 		}
 		if s.deletes != 0 || s.deletedDirs != 0 {
-			_, _ = fmt.Fprintf(buf, "Deleted:       %10d (files), %d (dirs)\n", s.deletes, s.deletedDirs)
+			_, _ = fmt.Fprintf(buf, "Deleted:       %10d (files), %d (dirs), %s (freed)\n", s.deletes, s.deletedDirs, fs.SizeSuffix(s.deletesSize).ByteUnit())
 		}
 		if s.renames != 0 {
 			_, _ = fmt.Fprintf(buf, "Renamed:       %10d\n", s.renames)
diff --git a/fs/config/config_read_password.go b/fs/config/config_read_password.go
index 2ea907372..8f3c79933 100644
--- a/fs/config/config_read_password.go
+++ b/fs/config/config_read_password.go
@@ -2,7 +2,6 @@
 // See https://github.com/golang/go/issues/14441 - plan9
 
 //go:build !plan9
-// +build !plan9
 
 package config
 
diff --git a/fs/config/config_read_password_unsupported.go b/fs/config/config_read_password_unsupported.go
index 364da802b..a9d8a6702 100644
--- a/fs/config/config_read_password_unsupported.go
+++ b/fs/config/config_read_password_unsupported.go
@@ -2,7 +2,6 @@
 // See https://github.com/golang/go/issues/14441 - plan9
 
 //go:build plan9
-// +build plan9
 
 package config
 
diff --git a/fs/config/configfile/configfile_other.go b/fs/config/configfile/configfile_other.go
index a2380d94c..ef509430c 100644
--- a/fs/config/configfile/configfile_other.go
+++ b/fs/config/configfile/configfile_other.go
@@ -2,7 +2,6 @@
 // Non-unix specific functions.
 
 //go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris
-// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
 
 package configfile
 
diff --git a/fs/config/configfile/configfile_unix.go b/fs/config/configfile/configfile_unix.go
index eb985b8b4..542e24621 100644
--- a/fs/config/configfile/configfile_unix.go
+++ b/fs/config/configfile/configfile_unix.go
@@ -2,7 +2,6 @@
 // Unix specific functions.
 
 //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
 
 package configfile
 
diff --git a/fs/daemon_other.go b/fs/daemon_other.go
index c012ba735..4e8043701 100644
--- a/fs/daemon_other.go
+++ b/fs/daemon_other.go
@@ -1,7 +1,6 @@
 // Daemonization stub for non-Unix platforms (common definitions)
 
 //go:build windows || plan9 || js
-// +build windows plan9 js
 
 package fs
 
diff --git a/fs/daemon_unix.go b/fs/daemon_unix.go
index 8951cbbc7..04c128508 100644
--- a/fs/daemon_unix.go
+++ b/fs/daemon_unix.go
@@ -1,7 +1,6 @@
 // Daemonization interface for Unix platforms (common definitions)
 
 //go:build !windows && !plan9 && !js
-// +build !windows,!plan9,!js
 
 package fs
 
diff --git a/fs/driveletter/driveletter.go b/fs/driveletter/driveletter.go
index 0c02f3976..68051473d 100644
--- a/fs/driveletter/driveletter.go
+++ b/fs/driveletter/driveletter.go
@@ -1,5 +1,4 @@
 //go:build !windows
-// +build !windows
 
 // Package driveletter returns whether a name is a valid drive letter
 package driveletter
diff --git a/fs/driveletter/driveletter_windows.go b/fs/driveletter/driveletter_windows.go
index f8b506a80..b66ec142d 100644
--- a/fs/driveletter/driveletter_windows.go
+++ b/fs/driveletter/driveletter_windows.go
@@ -1,5 +1,4 @@
 //go:build windows
-// +build windows
 
 // Package driveletter returns whether a name is a valid drive letter
 package driveletter
diff --git a/fs/fserrors/enospc_error.go b/fs/fserrors/enospc_error.go
index 410b513b1..bbb424e46 100644
--- a/fs/fserrors/enospc_error.go
+++ b/fs/fserrors/enospc_error.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 package fserrors
 
diff --git a/fs/fserrors/enospc_error_notsupported.go b/fs/fserrors/enospc_error_notsupported.go
index f71231c17..30f5a6b3c 100644
--- a/fs/fserrors/enospc_error_notsupported.go
+++ b/fs/fserrors/enospc_error_notsupported.go
@@ -1,5 +1,4 @@
 //go:build plan9
-// +build plan9
 
 package fserrors
 
diff --git a/fs/fserrors/retriable_errors.go b/fs/fserrors/retriable_errors.go
index 6dd48248f..bd24f0a8e 100644
--- a/fs/fserrors/retriable_errors.go
+++ b/fs/fserrors/retriable_errors.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 package fserrors
 
diff --git a/fs/fserrors/retriable_errors_windows.go b/fs/fserrors/retriable_errors_windows.go
index 9c5ff061f..58751c50f 100644
--- a/fs/fserrors/retriable_errors_windows.go
+++ b/fs/fserrors/retriable_errors_windows.go
@@ -1,5 +1,4 @@
 //go:build windows
-// +build windows
 
 package fserrors
 
diff --git a/fs/fspath/fuzz.go b/fs/fspath/fuzz.go
index c40095059..226f26a4b 100644
--- a/fs/fspath/fuzz.go
+++ b/fs/fspath/fuzz.go
@@ -1,5 +1,4 @@
 //go:build gofuzz
-// +build gofuzz
 
 /*
    Fuzz test the Parse function
diff --git a/fs/log/redirect_stderr.go b/fs/log/redirect_stderr.go
index b4e99ef2a..ce10ed36a 100644
--- a/fs/log/redirect_stderr.go
+++ b/fs/log/redirect_stderr.go
@@ -1,7 +1,6 @@
 // Log the panic to the log file - for oses which can't do this
 
 //go:build !windows && !darwin && !dragonfly && !freebsd && !linux && !nacl && !netbsd && !openbsd
-// +build !windows,!darwin,!dragonfly,!freebsd,!linux,!nacl,!netbsd,!openbsd
 
 package log
 
diff --git a/fs/log/redirect_stderr_unix.go b/fs/log/redirect_stderr_unix.go
index e0b8e4eca..f37a89204 100644
--- a/fs/log/redirect_stderr_unix.go
+++ b/fs/log/redirect_stderr_unix.go
@@ -1,7 +1,6 @@
 // Log the panic under unix to the log file
 
 //go:build !windows && !solaris && !plan9 && !js
-// +build !windows,!solaris,!plan9,!js
 
 package log
 
diff --git a/fs/log/redirect_stderr_windows.go b/fs/log/redirect_stderr_windows.go
index f55f144f7..7a7e8cfc1 100644
--- a/fs/log/redirect_stderr_windows.go
+++ b/fs/log/redirect_stderr_windows.go
@@ -5,7 +5,6 @@
 // https://play.golang.org/p/kLtct7lSUg
 
 //go:build windows
-// +build windows
 
 package log
 
diff --git a/fs/log/syslog.go b/fs/log/syslog.go
index 84c84c908..58b82ac9f 100644
--- a/fs/log/syslog.go
+++ b/fs/log/syslog.go
@@ -1,7 +1,6 @@
 // Syslog interface for non-Unix variants only
 
 //go:build windows || nacl || plan9
-// +build windows nacl plan9
 
 package log
 
diff --git a/fs/log/syslog_unix.go b/fs/log/syslog_unix.go
index ea0d3645a..7d7efe8ee 100644
--- a/fs/log/syslog_unix.go
+++ b/fs/log/syslog_unix.go
@@ -1,7 +1,6 @@
 // Syslog interface for Unix variants only
 
 //go:build !windows && !nacl && !plan9
-// +build !windows,!nacl,!plan9
 
 package log
 
diff --git a/fs/log/systemd.go b/fs/log/systemd.go
index c09227b09..2caf675da 100644
--- a/fs/log/systemd.go
+++ b/fs/log/systemd.go
@@ -1,7 +1,6 @@
 // Systemd interface for non-Unix variants only
 
 //go:build !unix
-// +build !unix
 
 package log
 
diff --git a/fs/log/systemd_unix.go b/fs/log/systemd_unix.go
index fa6700734..cf78d35a8 100644
--- a/fs/log/systemd_unix.go
+++ b/fs/log/systemd_unix.go
@@ -1,7 +1,6 @@
 // Systemd interface for Unix variants only
 
 //go:build unix
-// +build unix
 
 package log
 
diff --git a/fs/metadata_mapper_code.go b/fs/metadata_mapper_code.go
index 9f402df11..d551984db 100644
--- a/fs/metadata_mapper_code.go
+++ b/fs/metadata_mapper_code.go
@@ -1,5 +1,4 @@
 //go:build ignore
-// +build ignore
 
 // A simple metadata mapper for testing purposes
 package main
diff --git a/fs/rc/js/main.go b/fs/rc/js/main.go
index eb536573e..f13e88903 100644
--- a/fs/rc/js/main.go
+++ b/fs/rc/js/main.go
@@ -3,7 +3,6 @@
 // This library exports the core rc functionality
 
 //go:build js
-// +build js
 
 package main
 
diff --git a/fs/rc/js/serve.go b/fs/rc/js/serve.go
index 30e38e44d..9f7822730 100644
--- a/fs/rc/js/serve.go
+++ b/fs/rc/js/serve.go
@@ -1,5 +1,4 @@
 //go:build none
-// +build none
 
 package main
 
diff --git a/fs/versioncheck.go b/fs/versioncheck.go
index 263d31013..58571a42a 100644
--- a/fs/versioncheck.go
+++ b/fs/versioncheck.go
@@ -1,5 +1,4 @@
 //go:build !go1.20
-// +build !go1.20
 
 package fs
 
diff --git a/lib/atexit/atexit_other.go b/lib/atexit/atexit_other.go
index 90dc70107..46b9088f2 100644
--- a/lib/atexit/atexit_other.go
+++ b/lib/atexit/atexit_other.go
@@ -1,5 +1,4 @@
 //go:build windows || plan9
-// +build windows plan9
 
 package atexit
 
diff --git a/lib/atexit/atexit_unix.go b/lib/atexit/atexit_unix.go
index 13c3e292a..9c50171b3 100644
--- a/lib/atexit/atexit_unix.go
+++ b/lib/atexit/atexit_unix.go
@@ -1,5 +1,4 @@
 //go:build !windows && !plan9
-// +build !windows,!plan9
 
 package atexit
 
diff --git a/lib/buildinfo/cgo.go b/lib/buildinfo/cgo.go
index 06af926cd..b30d86380 100644
--- a/lib/buildinfo/cgo.go
+++ b/lib/buildinfo/cgo.go
@@ -1,5 +1,4 @@
 //go:build cgo
-// +build cgo
 
 package buildinfo
 
diff --git a/lib/buildinfo/osversion.go b/lib/buildinfo/osversion.go
index b398702d5..8a652613d 100644
--- a/lib/buildinfo/osversion.go
+++ b/lib/buildinfo/osversion.go
@@ -1,5 +1,4 @@
 //go:build !windows
-// +build !windows
 
 package buildinfo
 
diff --git a/lib/buildinfo/snap.go b/lib/buildinfo/snap.go
index 0cc8abd21..64270f15e 100644
--- a/lib/buildinfo/snap.go
+++ b/lib/buildinfo/snap.go
@@ -1,5 +1,4 @@
 //go:build snap
-// +build snap
 
 package buildinfo
 
diff --git a/lib/encoder/filename/fuzz.go b/lib/encoder/filename/fuzz.go
index e0843f04c..63fb94e29 100644
--- a/lib/encoder/filename/fuzz.go
+++ b/lib/encoder/filename/fuzz.go
@@ -1,5 +1,4 @@
 //go:build gofuzz
-// +build gofuzz
 
 package filename
 
diff --git a/lib/encoder/filename/gentable.go b/lib/encoder/filename/gentable.go
index 2fb5ed8a6..2d45b6e8c 100644
--- a/lib/encoder/filename/gentable.go
+++ b/lib/encoder/filename/gentable.go
@@ -1,5 +1,4 @@
 //go:build ignore
-// +build ignore
 
 package main
 
diff --git a/lib/encoder/os_darwin.go b/lib/encoder/os_darwin.go
index 70dad00ab..053afc3a1 100644
--- a/lib/encoder/os_darwin.go
+++ b/lib/encoder/os_darwin.go
@@ -1,5 +1,4 @@
 //go:build darwin
-// +build darwin
 
 package encoder
 
diff --git a/lib/encoder/os_other.go b/lib/encoder/os_other.go
index 9fa043570..34279d7ca 100644
--- a/lib/encoder/os_other.go
+++ b/lib/encoder/os_other.go
@@ -1,5 +1,4 @@
 //go:build !windows && !darwin
-// +build !windows,!darwin
 
 package encoder
 
diff --git a/lib/encoder/os_windows.go b/lib/encoder/os_windows.go
index 7e3c4dd87..1c450dc1c 100644
--- a/lib/encoder/os_windows.go
+++ b/lib/encoder/os_windows.go
@@ -1,5 +1,4 @@
 //go:build windows
-// +build windows
 
 package encoder
 
diff --git a/lib/file/driveletter_other.go b/lib/file/driveletter_other.go
index f18855823..1ae5284a6 100644
--- a/lib/file/driveletter_other.go
+++ b/lib/file/driveletter_other.go
@@ -1,5 +1,4 @@
 //go:build !windows
-// +build !windows
 
 package file
 
diff --git a/lib/file/driveletter_windows.go b/lib/file/driveletter_windows.go
index 352907ab9..ad71ad3c2 100644
--- a/lib/file/driveletter_windows.go
+++ b/lib/file/driveletter_windows.go
@@ -1,5 +1,4 @@
 //go:build windows
-// +build windows
 
 package file
 
diff --git a/lib/file/file_other.go b/lib/file/file_other.go
index cfa8cf0f1..d97a4250b 100644
--- a/lib/file/file_other.go
+++ b/lib/file/file_other.go
@@ -1,5 +1,4 @@
 //go:build !windows
-// +build !windows
 
 package file
 
diff --git a/lib/file/file_windows.go b/lib/file/file_windows.go
index 0f797f731..7840f98e1 100644
--- a/lib/file/file_windows.go
+++ b/lib/file/file_windows.go
@@ -1,5 +1,4 @@
 //go:build windows
-// +build windows
 
 package file
 
diff --git a/lib/file/mkdir_other.go b/lib/file/mkdir_other.go
index 9f49826a2..6baa7566b 100644
--- a/lib/file/mkdir_other.go
+++ b/lib/file/mkdir_other.go
@@ -1,5 +1,4 @@
 //go:build !windows
-// +build !windows
 
 package file
 
diff --git a/lib/file/mkdir_windows.go b/lib/file/mkdir_windows.go
index 929587fd8..d5a875ec3 100644
--- a/lib/file/mkdir_windows.go
+++ b/lib/file/mkdir_windows.go
@@ -1,5 +1,4 @@
 //go:build windows
-// +build windows
 
 package file
 
diff --git a/lib/file/preallocate_other.go b/lib/file/preallocate_other.go
index bcb2f2783..f9620cad1 100644
--- a/lib/file/preallocate_other.go
+++ b/lib/file/preallocate_other.go
@@ -1,5 +1,4 @@
 //go:build !windows && !linux
-// +build !windows,!linux
 
 package file
 
diff --git a/lib/file/preallocate_unix.go b/lib/file/preallocate_unix.go
index 3ffefb20d..9af350576 100644
--- a/lib/file/preallocate_unix.go
+++ b/lib/file/preallocate_unix.go
@@ -1,5 +1,4 @@
 //go:build linux
-// +build linux
 
 package file
 
diff --git a/lib/file/preallocate_windows.go b/lib/file/preallocate_windows.go
index 39955092e..e1d0c1a01 100644
--- a/lib/file/preallocate_windows.go
+++ b/lib/file/preallocate_windows.go
@@ -1,5 +1,4 @@
 //go:build windows
-// +build windows
 
 package file
 
diff --git a/lib/file/unc.go b/lib/file/unc.go
index c55573dc3..9832f7ab5 100644
--- a/lib/file/unc.go
+++ b/lib/file/unc.go
@@ -1,5 +1,4 @@
 //go:build !windows
-// +build !windows
 
 package file
 
diff --git a/lib/file/unc_windows.go b/lib/file/unc_windows.go
index 36cadf1d2..5038b2198 100644
--- a/lib/file/unc_windows.go
+++ b/lib/file/unc_windows.go
@@ -1,5 +1,4 @@
 //go:build windows
-// +build windows
 
 package file
 
diff --git a/lib/israce/israce.go b/lib/israce/israce.go
index 99371f530..450785e07 100644
--- a/lib/israce/israce.go
+++ b/lib/israce/israce.go
@@ -1,5 +1,4 @@
 //go:build race
-// +build race
 
 // Package israce reports if the Go race detector is enabled.
 //
diff --git a/lib/israce/norace.go b/lib/israce/norace.go
index ecede869b..556268fe0 100644
--- a/lib/israce/norace.go
+++ b/lib/israce/norace.go
@@ -1,5 +1,4 @@
 //go:build !race
-// +build !race
 
 // Package israce reports if the Go race detector is enabled.
 //
diff --git a/lib/kv/bolt.go b/lib/kv/bolt.go
index 7ae5756ad..39cf2ed15 100644
--- a/lib/kv/bolt.go
+++ b/lib/kv/bolt.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !js
-// +build !plan9,!js
 
 // Package kv provides key/value database.
 package kv
diff --git a/lib/kv/unsupported.go b/lib/kv/unsupported.go
index 9148a1806..cf2f5d56a 100644
--- a/lib/kv/unsupported.go
+++ b/lib/kv/unsupported.go
@@ -1,5 +1,4 @@
 //go:build plan9 || js
-// +build plan9 js
 
 package kv
 
diff --git a/lib/mmap/mmap_unix.go b/lib/mmap/mmap_unix.go
index be7cf195c..8bc9e2e22 100644
--- a/lib/mmap/mmap_unix.go
+++ b/lib/mmap/mmap_unix.go
@@ -2,7 +2,6 @@
 // anonymous memory maps.
 
 //go:build !plan9 && !windows && !js
-// +build !plan9,!windows,!js
 
 package mmap
 
diff --git a/lib/mmap/mmap_unsupported.go b/lib/mmap/mmap_unsupported.go
index 264a4df46..e78817da7 100644
--- a/lib/mmap/mmap_unsupported.go
+++ b/lib/mmap/mmap_unsupported.go
@@ -1,7 +1,6 @@
 // Fallback Alloc and Free for unsupported OSes
 
 //go:build plan9 || js
-// +build plan9 js
 
 package mmap
 
diff --git a/lib/mmap/mmap_windows.go b/lib/mmap/mmap_windows.go
index 5c45ac89b..f2f3c672e 100644
--- a/lib/mmap/mmap_windows.go
+++ b/lib/mmap/mmap_windows.go
@@ -2,7 +2,6 @@
 // anonymous memory maps.
 
 //go:build windows
-// +build windows
 
 package mmap
 
diff --git a/lib/plugin/plugin.go b/lib/plugin/plugin.go
index a57b83c0e..b8bf9fc33 100644
--- a/lib/plugin/plugin.go
+++ b/lib/plugin/plugin.go
@@ -1,6 +1,4 @@
 //go:build (darwin || linux) && !gccgo
-// +build darwin linux
-// +build !gccgo
 
 package plugin
 
diff --git a/lib/terminal/hidden_other.go b/lib/terminal/hidden_other.go
index e5bf08ca9..cab0caf51 100644
--- a/lib/terminal/hidden_other.go
+++ b/lib/terminal/hidden_other.go
@@ -1,5 +1,4 @@
 //go:build !windows
-// +build !windows
 
 package terminal
 
diff --git a/lib/terminal/hidden_windows.go b/lib/terminal/hidden_windows.go
index 5ef539fbe..cd0a980b0 100644
--- a/lib/terminal/hidden_windows.go
+++ b/lib/terminal/hidden_windows.go
@@ -1,5 +1,4 @@
 //go:build windows
-// +build windows
 
 package terminal
 
diff --git a/lib/terminal/terminal_normal.go b/lib/terminal/terminal_normal.go
index f84affbaa..8b10212f6 100644
--- a/lib/terminal/terminal_normal.go
+++ b/lib/terminal/terminal_normal.go
@@ -1,5 +1,4 @@
 //go:build !js
-// +build !js
 
 package terminal
 
diff --git a/lib/terminal/terminal_unsupported.go b/lib/terminal/terminal_unsupported.go
index d1e743d2c..6a2c98ceb 100644
--- a/lib/terminal/terminal_unsupported.go
+++ b/lib/terminal/terminal_unsupported.go
@@ -1,5 +1,4 @@
 //go:build js
-// +build js
 
 package terminal
 
diff --git a/vfs/vfsflags/vfsflags_non_unix.go b/vfs/vfsflags/vfsflags_non_unix.go
index dd7250e57..68c2af5ac 100644
--- a/vfs/vfsflags/vfsflags_non_unix.go
+++ b/vfs/vfsflags/vfsflags_non_unix.go
@@ -1,5 +1,4 @@
 //go:build !linux && !darwin && !freebsd
-// +build !linux,!darwin,!freebsd
 
 package vfsflags
 
diff --git a/vfs/vfsflags/vfsflags_unix.go b/vfs/vfsflags/vfsflags_unix.go
index cfffad6fb..83af3f2a8 100644
--- a/vfs/vfsflags/vfsflags_unix.go
+++ b/vfs/vfsflags/vfsflags_unix.go
@@ -1,5 +1,4 @@
 //go:build linux || darwin || freebsd
-// +build linux darwin freebsd
 
 package vfsflags
 


Test patch:
diff --git a/backend/azureblob/azureblob_internal_test.go b/backend/azureblob/azureblob_internal_test.go
index 2479c3624..f1606cdc3 100644
--- a/backend/azureblob/azureblob_internal_test.go
+++ b/backend/azureblob/azureblob_internal_test.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !solaris && !js
-// +build !plan9,!solaris,!js
 
 package azureblob
 
diff --git a/backend/azureblob/azureblob_test.go b/backend/azureblob/azureblob_test.go
index 7caf51233..1d498bb82 100644
--- a/backend/azureblob/azureblob_test.go
+++ b/backend/azureblob/azureblob_test.go
@@ -1,7 +1,6 @@
 // Test AzureBlob filesystem interface
 
 //go:build !plan9 && !solaris && !js
-// +build !plan9,!solaris,!js
 
 package azureblob
 
diff --git a/backend/azurefiles/azurefiles_internal_test.go b/backend/azurefiles/azurefiles_internal_test.go
index b123ad730..77e0156cc 100644
--- a/backend/azurefiles/azurefiles_internal_test.go
+++ b/backend/azurefiles/azurefiles_internal_test.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !js
-// +build !plan9,!js
 
 package azurefiles
 
diff --git a/backend/azurefiles/azurefiles_test.go b/backend/azurefiles/azurefiles_test.go
index d8091fa49..987d08494 100644
--- a/backend/azurefiles/azurefiles_test.go
+++ b/backend/azurefiles/azurefiles_test.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !js
-// +build !plan9,!js
 
 package azurefiles
 
diff --git a/backend/cache/cache_internal_test.go b/backend/cache/cache_internal_test.go
index 5c7d19c6d..cd75f2d2b 100644
--- a/backend/cache/cache_internal_test.go
+++ b/backend/cache/cache_internal_test.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !js && !race
-// +build !plan9,!js,!race
 
 package cache_test
 
diff --git a/backend/cache/cache_test.go b/backend/cache/cache_test.go
index faf33e5d7..41ed7e48c 100644
--- a/backend/cache/cache_test.go
+++ b/backend/cache/cache_test.go
@@ -1,7 +1,6 @@
 // Test Cache filesystem interface
 
 //go:build !plan9 && !js && !race
-// +build !plan9,!js,!race
 
 package cache_test
 
diff --git a/backend/cache/cache_upload_test.go b/backend/cache/cache_upload_test.go
index d0246740a..0a3e5d297 100644
--- a/backend/cache/cache_upload_test.go
+++ b/backend/cache/cache_upload_test.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !js && !race
-// +build !plan9,!js,!race
 
 package cache_test
 
diff --git a/backend/hdfs/hdfs_test.go b/backend/hdfs/hdfs_test.go
index cb2ff6c22..edbb62330 100644
--- a/backend/hdfs/hdfs_test.go
+++ b/backend/hdfs/hdfs_test.go
@@ -1,7 +1,6 @@
 // Test HDFS filesystem interface
 
 //go:build !plan9
-// +build !plan9
 
 package hdfs_test
 
diff --git a/backend/oracleobjectstorage/oracleobjectstorage_test.go b/backend/oracleobjectstorage/oracleobjectstorage_test.go
index daccfaeed..f41dfb605 100644
--- a/backend/oracleobjectstorage/oracleobjectstorage_test.go
+++ b/backend/oracleobjectstorage/oracleobjectstorage_test.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !solaris && !js
-// +build !plan9,!solaris,!js
 
 package oracleobjectstorage
 
diff --git a/backend/qingstor/qingstor_test.go b/backend/qingstor/qingstor_test.go
index f7e211134..d599b79e0 100644
--- a/backend/qingstor/qingstor_test.go
+++ b/backend/qingstor/qingstor_test.go
@@ -1,7 +1,6 @@
 // Test QingStor filesystem interface
 
 //go:build !plan9 && !js
-// +build !plan9,!js
 
 package qingstor
 
diff --git a/backend/sftp/sftp_internal_test.go b/backend/sftp/sftp_internal_test.go
index 0803321c8..e799f6654 100644
--- a/backend/sftp/sftp_internal_test.go
+++ b/backend/sftp/sftp_internal_test.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 package sftp
 
diff --git a/backend/sftp/sftp_test.go b/backend/sftp/sftp_test.go
index c5ee136a5..2e9ad9f20 100644
--- a/backend/sftp/sftp_test.go
+++ b/backend/sftp/sftp_test.go
@@ -1,7 +1,6 @@
 // Test Sftp filesystem interface
 
 //go:build !plan9
-// +build !plan9
 
 package sftp_test
 
diff --git a/backend/sftp/stringlock_test.go b/backend/sftp/stringlock_test.go
index 41b46a441..bc89a0147 100644
--- a/backend/sftp/stringlock_test.go
+++ b/backend/sftp/stringlock_test.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 package sftp
 
diff --git a/backend/storj/storj_test.go b/backend/storj/storj_test.go
index 9213f1b10..c1678baa0 100644
--- a/backend/storj/storj_test.go
+++ b/backend/storj/storj_test.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 // Test Storj filesystem interface
 package storj_test
diff --git a/backend/union/errors_test.go b/backend/union/errors_test.go
index 3d79a69b0..e7f770c35 100644
--- a/backend/union/errors_test.go
+++ b/backend/union/errors_test.go
@@ -1,5 +1,4 @@
 //go:build go1.20
-// +build go1.20
 
 package union
 
diff --git a/bin/test_independence.go b/bin/test_independence.go
index 12aab97be..efe4b7975 100644
--- a/bin/test_independence.go
+++ b/bin/test_independence.go
@@ -1,5 +1,4 @@
 //go:build ignore
-// +build ignore
 
 // Test that the tests in the suite passed in are independent
 
diff --git a/cmd/bisync/bisync_test.go b/cmd/bisync/bisync_test.go
index dbf009aa3..5824a5557 100644
--- a/cmd/bisync/bisync_test.go
+++ b/cmd/bisync/bisync_test.go
@@ -335,13 +335,23 @@ func testBisync(t *testing.T, path1, path2 string) {
 		}
 	}
 	require.False(t, b.stopAt > 0 && len(testList) > 1, "-stop-at is meaningful only for a single test")
+	deadline, hasDeadline := t.Deadline()
+	var maxRunDuration time.Duration
 
 	for _, testCase := range testList {
 		testCase = strings.ReplaceAll(testCase, "-", "_")
 		testCase = strings.TrimPrefix(testCase, "test_")
 		t.Run(testCase, func(childTest *testing.T) {
+			startTime := time.Now()
+			remaining := time.Until(deadline)
+			if hasDeadline && (remaining < maxRunDuration || remaining < 10*time.Second) { // avoid starting tests we don't have time to finish
+				childTest.Fatalf("test %v timed out - not enough time to start test (%v remaining, need %v for test)", testCase, remaining, maxRunDuration)
+			}
 			bCopy := *b
 			bCopy.runTestCase(ctx, childTest, testCase)
+			if time.Since(startTime) > maxRunDuration {
+				maxRunDuration = time.Since(startTime)
+			}
 		})
 	}
 }
@@ -368,6 +378,10 @@ func (b *bisyncTest) runTestCase(ctx context.Context, t *testing.T, testCase str
 	b.fs1, b.parent1, b.path1, b.canonPath1 = b.makeTempRemote(ctx, b.argRemote1, "path1")
 	b.fs2, b.parent2, b.path2, b.canonPath2 = b.makeTempRemote(ctx, b.argRemote2, "path2")
 
+	if strings.Contains(b.replaceHex(b.path1), " ") || strings.Contains(b.replaceHex(b.path2), " ") {
+		b.t.Skip("skipping as tests can't handle spaces config string")
+	}
+
 	b.sessionName = bilib.SessionName(b.fs1, b.fs2)
 	b.testDir = b.ensureDir(b.dataRoot, "test_"+b.testCase, false)
 	b.initDir = b.ensureDir(b.testDir, "initial", false)
diff --git a/cmd/cmount/mount_test.go b/cmd/cmount/mount_test.go
index 8da6116e2..e0cc1c4ca 100644
--- a/cmd/cmount/mount_test.go
+++ b/cmd/cmount/mount_test.go
@@ -1,7 +1,4 @@
 //go:build cmount && ((linux && cgo) || (darwin && cgo) || (freebsd && cgo) || windows) && (!race || !windows)
-// +build cmount
-// +build linux,cgo darwin,cgo freebsd,cgo windows
-// +build !race !windows
 
 // Package cmount implements a FUSE mounting system for rclone remotes.
 //
diff --git a/cmd/mount/mount_test.go b/cmd/mount/mount_test.go
index df4d02ec0..0e4a0483d 100644
--- a/cmd/mount/mount_test.go
+++ b/cmd/mount/mount_test.go
@@ -1,5 +1,4 @@
 //go:build linux
-// +build linux
 
 package mount
 
diff --git a/cmd/mount/test/seek_speed.go b/cmd/mount/test/seek_speed.go
index 55d5bfa59..525e35510 100644
--- a/cmd/mount/test/seek_speed.go
+++ b/cmd/mount/test/seek_speed.go
@@ -1,5 +1,4 @@
 //go:build ignore
-// +build ignore
 
 // Read blocks out of a single file to time the seeking code
 package main
diff --git a/cmd/mount/test/seeker.go b/cmd/mount/test/seeker.go
index 42a2f0e9e..d4a58fb09 100644
--- a/cmd/mount/test/seeker.go
+++ b/cmd/mount/test/seeker.go
@@ -1,5 +1,4 @@
 //go:build ignore
-// +build ignore
 
 // Read two files with lots of seeking to stress test the seek code
 package main
diff --git a/cmd/mount/test/seekers.go b/cmd/mount/test/seekers.go
index 571ecf87b..a0433891d 100644
--- a/cmd/mount/test/seekers.go
+++ b/cmd/mount/test/seekers.go
@@ -1,5 +1,4 @@
 //go:build ignore
-// +build ignore
 
 // Read lots files with lots of simultaneous seeking to stress test the seek code
 package main
diff --git a/cmd/mount2/mount_test.go b/cmd/mount2/mount_test.go
index 5ff74ff3c..a5bb9950d 100644
--- a/cmd/mount2/mount_test.go
+++ b/cmd/mount2/mount_test.go
@@ -1,5 +1,4 @@
 //go:build linux
-// +build linux
 
 package mount2
 
diff --git a/cmd/nfsmount/nfsmount_test.go b/cmd/nfsmount/nfsmount_test.go
index d4c9c3441..df982358c 100644
--- a/cmd/nfsmount/nfsmount_test.go
+++ b/cmd/nfsmount/nfsmount_test.go
@@ -1,5 +1,4 @@
 //go:build darwin && !cmount
-// +build darwin,!cmount
 
 package nfsmount
 
diff --git a/cmd/selfupdate/selfupdate_test.go b/cmd/selfupdate/selfupdate_test.go
index 032c28bec..263f8049c 100644
--- a/cmd/selfupdate/selfupdate_test.go
+++ b/cmd/selfupdate/selfupdate_test.go
@@ -1,5 +1,4 @@
 //go:build !noselfupdate
-// +build !noselfupdate
 
 package selfupdate
 
diff --git a/cmd/selfupdate/verify_test.go b/cmd/selfupdate/verify_test.go
index bf3e7754d..2c8519f40 100644
--- a/cmd/selfupdate/verify_test.go
+++ b/cmd/selfupdate/verify_test.go
@@ -1,5 +1,4 @@
 //go:build !noselfupdate
-// +build !noselfupdate
 
 package selfupdate
 
diff --git a/cmd/serve/docker/docker_test.go b/cmd/serve/docker/docker_test.go
index 4346b2f92..a4b1cd320 100644
--- a/cmd/serve/docker/docker_test.go
+++ b/cmd/serve/docker/docker_test.go
@@ -1,5 +1,4 @@
 //go:build !race
-// +build !race
 
 package docker_test
 
diff --git a/cmd/serve/ftp/ftp_test.go b/cmd/serve/ftp/ftp_test.go
index 59fd59b8d..a90744d52 100644
--- a/cmd/serve/ftp/ftp_test.go
+++ b/cmd/serve/ftp/ftp_test.go
@@ -4,7 +4,6 @@
 // We skip tests on platforms with troublesome character mappings
 
 //go:build !windows && !darwin && !plan9
-// +build !windows,!darwin,!plan9
 
 package ftp
 
diff --git a/cmd/serve/servetest/proxy_code.go b/cmd/serve/servetest/proxy_code.go
index 291f305fb..25499b6bc 100644
--- a/cmd/serve/servetest/proxy_code.go
+++ b/cmd/serve/servetest/proxy_code.go
@@ -1,5 +1,4 @@
 //go:build ignore
-// +build ignore
 
 // A simple auth proxy for testing purposes
 package main
diff --git a/cmd/serve/sftp/connection_test.go b/cmd/serve/sftp/connection_test.go
index e9f8830cd..b406e79f4 100644
--- a/cmd/serve/sftp/connection_test.go
+++ b/cmd/serve/sftp/connection_test.go
@@ -1,5 +1,4 @@
 //go:build !plan9
-// +build !plan9
 
 package sftp
 
diff --git a/cmd/serve/sftp/sftp_test.go b/cmd/serve/sftp/sftp_test.go
index 71305ba75..945b00f4b 100644
--- a/cmd/serve/sftp/sftp_test.go
+++ b/cmd/serve/sftp/sftp_test.go
@@ -4,7 +4,6 @@
 // We skip tests on platforms with troublesome character mappings
 
 //go:build !windows && !darwin && !plan9
-// +build !windows,!darwin,!plan9
 
 package sftp
 
diff --git a/cmd/serve/webdav/webdav_test.go b/cmd/serve/webdav/webdav_test.go
index 6734d6f6e..fe1524d43 100644
--- a/cmd/serve/webdav/webdav_test.go
+++ b/cmd/serve/webdav/webdav_test.go
@@ -4,7 +4,6 @@
 // We skip tests on platforms with troublesome character mappings
 
 //go:build !windows && !darwin
-// +build !windows,!darwin
 
 package webdav
 
diff --git a/fs/config/testdata/plain.conf b/fs/config/testdata/plain.conf
index f76f59566..1167d885b 100644
--- a/fs/config/testdata/plain.conf
+++ b/fs/config/testdata/plain.conf
@@ -1,12 +1,12 @@
-[RCLONE_ENCRYPT_V0]
-type = local
-nounc = true
-
-[nounc]
-type = local
-nounc = true
-
-
-[unc]
-type = local
-nounc = false
+[RCLONE_ENCRYPT_V0]
+type = local
+nounc = true
+
+[nounc]
+type = local
+nounc = true
+
+
+[unc]
+type = local
+nounc = false
diff --git a/lib/file/mkdir_windows_test.go b/lib/file/mkdir_windows_test.go
index a969f2d7f..5e6fdc60e 100644
--- a/lib/file/mkdir_windows_test.go
+++ b/lib/file/mkdir_windows_test.go
@@ -1,5 +1,4 @@
 //go:build windows
-// +build windows
 
 package file
 
diff --git a/lib/file/unc_test.go b/lib/file/unc_test.go
index d4bb2138e..bf82ddba7 100644
--- a/lib/file/unc_test.go
+++ b/lib/file/unc_test.go
@@ -1,5 +1,4 @@
 //go:build windows
-// +build windows
 
 package file
 
diff --git a/lib/kv/internal_test.go b/lib/kv/internal_test.go
index 1c0834fbb..5ff47b1a6 100644
--- a/lib/kv/internal_test.go
+++ b/lib/kv/internal_test.go
@@ -1,5 +1,4 @@
 //go:build !plan9 && !js
-// +build !plan9,!js
 
 package kv
 
diff --git a/vfs/make_open_tests.go b/vfs/make_open_tests.go
index d4e64f058..01df4d0a9 100644
--- a/vfs/make_open_tests.go
+++ b/vfs/make_open_tests.go
@@ -8,7 +8,6 @@
 // Run with go generate (defined in vfs.go)
 //
 //go:build none
-// +build none
 
 // FIXME include read too?
 
diff --git a/vfs/vfstest/read_non_unix.go b/vfs/vfstest/read_non_unix.go
index cbb60bbe5..d2328c8e3 100644
--- a/vfs/vfstest/read_non_unix.go
+++ b/vfs/vfstest/read_non_unix.go
@@ -1,5 +1,4 @@
 //go:build !linux && !darwin && !freebsd
-// +build !linux,!darwin,!freebsd
 
 package vfstest
 
diff --git a/vfs/vfstest/read_unix.go b/vfs/vfstest/read_unix.go
index afeeb197d..c5b1e881f 100644
--- a/vfs/vfstest/read_unix.go
+++ b/vfs/vfstest/read_unix.go
@@ -1,5 +1,4 @@
 //go:build linux || darwin || freebsd
-// +build linux darwin freebsd
 
 package vfstest
 
diff --git a/vfs/vfstest/write_non_unix.go b/vfs/vfstest/write_non_unix.go
index 637d5b5bd..161354434 100644
--- a/vfs/vfstest/write_non_unix.go
+++ b/vfs/vfstest/write_non_unix.go
@@ -1,5 +1,4 @@
 //go:build !linux && !darwin && !freebsd
-// +build !linux,!darwin,!freebsd
 
 package vfstest
 
diff --git a/vfs/vfstest/write_unix.go b/vfs/vfstest/write_unix.go
index 4ce40c970..981035822 100644
--- a/vfs/vfstest/write_unix.go
+++ b/vfs/vfstest/write_unix.go
@@ -1,5 +1,4 @@
 //go:build linux || darwin || freebsd
-// +build linux darwin freebsd
 
 package vfstest