Repository: rclone/rclone (language: go)

Issue:
Combined remotes - moving directory within different remotes fails
#### What are you trying to do?

Moving a folder from one remote to another.

It works within a combined remote with the `rclone move` command.
It works while the remotes are separately mounted (using `rclone mount` for each remote and then `mv`).

#### What is the problem you are having with rclone?

Moving a folder within two remotes while mounted as combined throws an e/a-error.
Moving a file or copying a folder this way works.

#### What is your rclone version (output from `rclone version`)

```
rclone v1.65.2
- os/version: arch (64 bit)
- os/kernel: 6.6.18-1-rpi-16k (aarch64)
- os/type: linux
- os/arch: arm64 (ARMv8 compatible)
- go/version: go1.21.7
- go/linking: dynamic
- go/tags: none
```

#### Which cloud storage systems are you using?

Dropbox, OneDrive, pCloud

#### The command you were trying to run

`root@raspberry ~ # rclone mount cloud: /mnt/cloud`
`root@raspberry ~ # mv /mnt/cloud/pcloud/8 /mnt/cloud/dropbox/`

#### A log from the command with the `-vv` flag

> 2024/03/06 10:08:28 DEBUG : rclone: Version "v1.65.2" starting with parameters ["rclone" "mount" "cloud:" "/mnt/cloud" "--config" "/etc/rclone.conf" "--log-level" "DEBUG" "--vfs-cache-mode" "writes"]
> 2024/03/06 10:08:28 DEBUG : Creating backend with remote "cloud:"
> 2024/03/06 10:08:28 DEBUG : Using config file from "/etc/rclone.conf"
> 2024/03/06 10:08:28 DEBUG : Creating backend with remote "pcloud:"
> 2024/03/06 10:08:28 DEBUG : Creating backend with remote "dropbox:"
> 2024/03/06 10:08:28 DEBUG : Creating backend with remote "onedrive:"
> 2024/03/06 10:08:29 DEBUG : vfs cache: root is "/root/.cache/rclone"
> 2024/03/06 10:08:29 DEBUG : vfs cache: data root is "/root/.cache/rclone/vfs/cloud"
> 2024/03/06 10:08:29 DEBUG : vfs cache: metadata root is "/root/.cache/rclone/vfsMeta/cloud"
> 2024/03/06 10:08:29 DEBUG : Creating backend with remote "/root/.cache/rclone/vfs/cloud/"
> 2024/03/06 10:08:29 DEBUG : fs cache: renaming cache item "/root/.cache/rclone/vfs/cloud/" to be canonical "/root/.cache/rclone/vfs/cloud"
> 2024/03/06 10:08:29 DEBUG : Creating backend with remote "/root/.cache/rclone/vfsMeta/cloud/"
> 2024/03/06 10:08:29 DEBUG : fs cache: renaming cache item "/root/.cache/rclone/vfsMeta/cloud/" to be canonical "/root/.cache/rclone/vfsMeta/cloud"
> 2024/03/06 10:08:29 INFO  : vfs cache: cleaned: objects 0 (was 0) in use 0, to upload 0, uploading 0, total size 0 (was 0)
> 2024/03/06 10:08:29 DEBUG : combine root '': Mounting on "/mnt/cloud"
> 2024/03/06 10:08:29 DEBUG : : Root:
> 2024/03/06 10:08:29 DEBUG : : >Root: node=/, err=<nil>
> 2024/03/06 10:08:30 DEBUG : OneDrive root '': Next delta token is: NDslMjM0OyUyMzE7Mzs1M2NmZmNmZC0zOGQwLTQwNDYtODZkOC01OTdlNWMwN2U0YTY7NjM4NDUzMTI5MDk5NjMwMDAwOzg1Nzc1NzE2OyUyMzslMjM7JTIzMDslMjM
> 2024/03/06 10:08:35 DEBUG : /: Lookup: name="pcloud"
> 2024/03/06 10:08:35 DEBUG : /: >Lookup: node=pcloud/, err=<nil>
> 2024/03/06 10:08:35 DEBUG : pcloud/: Attr:
> 2024/03/06 10:08:35 DEBUG : pcloud/: >Attr: attr=valid=1s ino=0 size=0 mode=drwxr-xr-x, err=<nil>
> 2024/03/06 10:08:35 DEBUG : pcloud/: Lookup: name="8"
> 2024/03/06 10:08:35 DEBUG : pcloud/: >Lookup: node=pcloud/8/, err=<nil>
> 2024/03/06 10:08:35 DEBUG : pcloud/8/: Attr:
> 2024/03/06 10:08:35 DEBUG : pcloud/8/: >Attr: attr=valid=1s ino=0 size=0 mode=drwxr-xr-x, err=<nil>
> 2024/03/06 10:08:35 DEBUG : /: Lookup: name="dropbox"
> 2024/03/06 10:08:35 DEBUG : /: >Lookup: node=dropbox/, err=<nil>
> 2024/03/06 10:08:35 DEBUG : dropbox/: Attr:
> 2024/03/06 10:08:35 DEBUG : dropbox/: >Attr: attr=valid=1s ino=0 size=0 mode=drwxr-xr-x, err=<nil>
> 2024/03/06 10:08:35 DEBUG : dropbox/: Lookup: name="8"
> 2024/03/06 10:08:36 DEBUG : dropbox/: >Lookup: node=<nil>, err=no such file or directory
> 2024/03/06 10:08:36 DEBUG : dropbox/: Lookup: name="8"
> 2024/03/06 10:08:36 DEBUG : dropbox/: >Lookup: node=<nil>, err=no such file or directory
> 2024/03/06 10:08:36 DEBUG : dropbox/: Lookup: name="8"
> 2024/03/06 10:08:36 DEBUG : dropbox/: >Lookup: node=<nil>, err=no such file or directory
> 2024/03/06 10:08:36 DEBUG : pcloud/: Rename: oldName="8", newName="8", newDir=dropbox/
> 2024/03/06 10:08:36 NOTICE: Dropbox root '': srcU.f=pcloud root '', srcURemote="8", dstURemote="8"
> 2024/03/06 10:08:36 DEBUG : <nil>: Can't move directory - not same remote type
> 2024/03/06 10:08:36 ERROR : pcloud/8: Dir.Rename error: can't move directory - incompatible remotes
> 2024/03/06 10:08:36 ERROR : IO error: can't move directory - incompatible remotes
> 2024/03/06 10:08:36 DEBUG : pcloud/: >Rename: err=can't move directory - incompatible remotes
> 2024/03/06 10:08:36 DEBUG : dropbox/: Lookup: name="8"
> 2024/03/06 10:08:36 DEBUG : dropbox/: >Lookup: node=<nil>, err=no such file or directory

#### Additional information

The folder exists on source but not destination:

> root@raspberry ~ # ls -al /mnt/cloud/pcloud/8
> insgesamt 1750
> drwxr-xr-x 1 root root      0  6. Mär 09:51 .
> drwxr-xr-x 1 root root      0  6. Mär 10:12 ..
> -rw-r--r-- 1 root root 666846  6. Mär 09:51 Freunde.jpg
> -rw-r--r-- 1 root root 189628  6. Mär 09:52 Glueckliche-familie.jpg
> -rw-r--r-- 1 root root  32905  6. Mär 09:51 Im-himmel.jpg
> -rw-r--r-- 1 root root 500130  6. Mär 09:51 Liebhaber.jpg
> -rw-r--r-- 1 root root 238222  6. Mär 09:51 Romantik.jpg
> -rw-r--r-- 1 root root 162388  6. Mär 09:51 Suessigkeiten.jpg
> root@raspberry ~ # ls -al /mnt/cloud/dropbox/8
> ls: Zugriff auf '/mnt/cloud/dropbox/8' nicht möglich: Datei oder Verzeichnis nicht gefunden

#### How to use GitHub

* Please use the 👍 [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to show that you are affected by the same issue.
* Please don't comment if you have no relevant information to add. It's just extra noise for everyone subscribed to this issue.
* Subscribe to receive notifications on status change and new comments.


Discussion / hints:
Could you please re-post it on the https://forum.rclone.org/ and close it here.

Github should be used for tracking confirmed bugs and requested enhancements only. Not for general troubleshooting.

Fix patch:
diff --git a/fs/operations/operations.go b/fs/operations/operations.go
index 125608fcf31de..415cfd6a7b88c 100644
--- a/fs/operations/operations.go
+++ b/fs/operations/operations.go
@@ -2269,7 +2269,10 @@ func DirMove(ctx context.Context, f fs.Fs, srcRemote, dstRemote string) (err err
 		if err == nil {
 			accounting.Stats(ctx).Renames(1)
 		}
-		return err
+		if err != fs.ErrorCantDirMove && err != fs.ErrorDirExists {
+			return err
+		}
+		fs.Infof(f, "Can't DirMove - falling back to file moves: %v", err)
 	}
 
 	// Load the directory tree into memory


Test patch:
diff --git a/fs/operations/operations_test.go b/fs/operations/operations_test.go
index 15143ee92b611..6f034bdb3ed7b 100644
--- a/fs/operations/operations_test.go
+++ b/fs/operations/operations_test.go
@@ -1405,6 +1405,33 @@ func TestDirMove(t *testing.T) {
 		fs.GetModifyWindow(ctx, r.Fremote),
 	)
 
+	// Try with a DirMove method that exists but returns fs.ErrorCantDirMove (ex. combine moving across upstreams)
+	// Should fall back to manual move (copy + delete)
+
+	features.DirMove = func(ctx context.Context, src fs.Fs, srcRemote string, dstRemote string) error {
+		return fs.ErrorCantDirMove
+	}
+
+	assert.NoError(t, operations.DirMove(ctx, r.Fremote, "A3", "A4"))
+
+	for i := range files {
+		files[i].Path = strings.ReplaceAll(files[i].Path, "A3/", "A4/")
+	}
+
+	fstest.CheckListingWithPrecision(
+		t,
+		r.Fremote,
+		files,
+		[]string{
+			"A4",
+			"A4/B1",
+			"A4/B2",
+			"A4/B1/C1",
+			"A4/B1/C2",
+			"A4/B1/C3",
+		},
+		fs.GetModifyWindow(ctx, r.Fremote),
+	)
 }
 
 func TestGetFsInfo(t *testing.T) {