diff --git a/fs/list/list.go b/fs/list/list.go index 09d47ac8f..50613779d 100644 --- a/fs/list/list.go +++ b/fs/list/list.go @@ -9,6 +9,7 @@ import ( "github.com/rclone/rclone/fs" "github.com/rclone/rclone/fs/filter" + "github.com/rclone/rclone/lib/bucket" ) // DirSorted reads Object and *Dir into entries for the given Fs. @@ -43,7 +44,10 @@ func filterAndSortDir(ctx context.Context, entries fs.DirEntries, includeAll boo newEntries = entries[:0] // in place filter prefix := "" if dir != "" { - prefix = dir + "/" + prefix = dir + if !bucket.IsAllSlashes(dir) { + prefix += "/" + } } for _, entry := range entries { ok := true @@ -77,10 +81,10 @@ func filterAndSortDir(ctx context.Context, entries fs.DirEntries, includeAll boo case !strings.HasPrefix(remote, prefix): ok = false fs.Errorf(entry, "Entry doesn't belong in directory %q (too short) - ignoring", dir) - case remote == prefix: + case remote == dir: ok = false fs.Errorf(entry, "Entry doesn't belong in directory %q (same as directory) - ignoring", dir) - case strings.ContainsRune(remote[len(prefix):], '/'): + case strings.ContainsRune(remote[len(prefix):], '/') && !bucket.IsAllSlashes(remote[len(prefix):]): ok = false fs.Errorf(entry, "Entry doesn't belong in directory %q (contains subdir) - ignoring", dir) default: diff --git a/fs/list/list_test.go b/fs/list/list_test.go index 616271746..94fa7a6cc 100644 --- a/fs/list/list_test.go +++ b/fs/list/list_test.go @@ -49,7 +49,8 @@ func TestFilterAndSortIncludeAll(t *testing.T) { func TestFilterAndSortCheckDir(t *testing.T) { // Check the different kinds of error when listing "dir" - da := mockdir.New("dir/") + da := mockdir.New("dir") + da2 := mockdir.New("dir/") // double slash dir - allowed for bucket based remotes oA := mockobject.Object("diR/a") db := mockdir.New("dir/b") oB := mockobject.Object("dir/B/sub") @@ -57,18 +58,19 @@ func TestFilterAndSortCheckDir(t *testing.T) { oC := mockobject.Object("dir/C") dd := mockdir.New("dir/d") oD := mockobject.Object("dir/D") - entries := fs.DirEntries{da, oA, db, oB, dc, oC, dd, oD} + entries := fs.DirEntries{da, da2, oA, db, oB, dc, oC, dd, oD} newEntries, err := filterAndSortDir(context.Background(), entries, true, "dir", nil, nil) require.NoError(t, err) assert.Equal(t, + fs.DirEntries{da2, oC, oD, db, dc, dd}, newEntries, - fs.DirEntries{oC, oD, db, dc, dd}, ) } func TestFilterAndSortCheckDirRoot(t *testing.T) { // Check the different kinds of error when listing the root "" da := mockdir.New("") + da2 := mockdir.New("/") // doubleslash dir allowed on bucket based remotes oA := mockobject.Object("A") db := mockdir.New("b") oB := mockobject.Object("B/sub") @@ -76,12 +78,12 @@ func TestFilterAndSortCheckDirRoot(t *testing.T) { oC := mockobject.Object("C") dd := mockdir.New("d") oD := mockobject.Object("D") - entries := fs.DirEntries{da, oA, db, oB, dc, oC, dd, oD} + entries := fs.DirEntries{da, da2, oA, db, oB, dc, oC, dd, oD} newEntries, err := filterAndSortDir(context.Background(), entries, true, "", nil, nil) require.NoError(t, err) assert.Equal(t, + fs.DirEntries{da2, oA, oC, oD, db, dc, dd}, newEntries, - fs.DirEntries{oA, oC, oD, db, dc, dd}, ) }