mirror of
https://github.com/rclone/rclone.git
synced 2024-11-26 10:25:03 +01:00
Fix and document the move command - fixes #334
* Don't attempt to use server side Move unless they are on the same Fs * Fix move in the presense of filters
This commit is contained in:
parent
ccb59480bd
commit
d2219a800a
@ -108,6 +108,22 @@ extended explanation in the `copy` command above if unsure.
|
|||||||
If dest:path doesn't exist, it is created and the source:path contents
|
If dest:path doesn't exist, it is created and the source:path contents
|
||||||
go there.
|
go there.
|
||||||
|
|
||||||
|
### move source:path dest:path ###
|
||||||
|
|
||||||
|
Moves the source to the destination.
|
||||||
|
|
||||||
|
If there are no filters in use this is equivalent to a copy followed
|
||||||
|
by a purge, but may using server side operations to speed it up if
|
||||||
|
possible.
|
||||||
|
|
||||||
|
If filters are in use then it is equivalent to a copy followed by
|
||||||
|
delete, followed by an rmdir (which only removes the directory if
|
||||||
|
empty). The individual file moves will be moved with srver side
|
||||||
|
operations if possible.
|
||||||
|
|
||||||
|
**Important**: Since this can cause data loss, test first with the
|
||||||
|
--dry-run flag.
|
||||||
|
|
||||||
### rclone ls remote:path ###
|
### rclone ls remote:path ###
|
||||||
|
|
||||||
List all the objects in the the path with size and path.
|
List all the objects in the the path with size and path.
|
||||||
|
@ -354,7 +354,7 @@ func PairMover(in ObjectPairChan, fdst Fs, wg *sync.WaitGroup) {
|
|||||||
Stats.Transferring(src)
|
Stats.Transferring(src)
|
||||||
if Config.DryRun {
|
if Config.DryRun {
|
||||||
Log(src, "Not moving as --dry-run")
|
Log(src, "Not moving as --dry-run")
|
||||||
} else if haveMover {
|
} else if haveMover && src.Fs().Name() == fdst.Name() {
|
||||||
// Delete destination if it exists
|
// Delete destination if it exists
|
||||||
if pair.dst != nil {
|
if pair.dst != nil {
|
||||||
err := dst.Remove()
|
err := dst.Remove()
|
||||||
@ -600,8 +600,8 @@ func MoveDir(fdst, fsrc Fs) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// First attempt to use DirMover
|
// First attempt to use DirMover if exists, same Fs and no filters are active
|
||||||
if fdstDirMover, ok := fdst.(DirMover); ok && fsrc.Name() == fdst.Name() {
|
if fdstDirMover, ok := fdst.(DirMover); ok && fsrc.Name() == fdst.Name() && Config.Filter.InActive() {
|
||||||
err := fdstDirMover.DirMove(fsrc)
|
err := fdstDirMover.DirMove(fsrc)
|
||||||
Debug(fdst, "Using server side directory move")
|
Debug(fdst, "Using server side directory move")
|
||||||
switch err {
|
switch err {
|
||||||
@ -623,7 +623,18 @@ func MoveDir(fdst, fsrc Fs) error {
|
|||||||
ErrorLog(fdst, "Not deleting files as there were IO errors")
|
ErrorLog(fdst, "Not deleting files as there were IO errors")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// If no filters then purge
|
||||||
|
if Config.Filter.InActive() {
|
||||||
return Purge(fsrc)
|
return Purge(fsrc)
|
||||||
|
}
|
||||||
|
// Otherwise remove any remaining files obeying filters
|
||||||
|
err = Delete(fsrc)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// and try to remove the directory if empty - ignoring error
|
||||||
|
_ = TryRmdir(fsrc)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the files in fsrc and fdst according to Size and hash
|
// Check the files in fsrc and fdst according to Size and hash
|
||||||
@ -849,18 +860,24 @@ func Mkdir(f Fs) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rmdir removes a container but not if not empty
|
// TryRmdir removes a container but not if not empty. It doesn't
|
||||||
func Rmdir(f Fs) error {
|
// count errors but may return one.
|
||||||
|
func TryRmdir(f Fs) error {
|
||||||
if Config.DryRun {
|
if Config.DryRun {
|
||||||
Log(f, "Not deleting as dry run is set")
|
Log(f, "Not deleting as dry run is set")
|
||||||
} else {
|
return nil
|
||||||
err := f.Rmdir()
|
}
|
||||||
|
return f.Rmdir()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rmdir removes a container but not if not empty
|
||||||
|
func Rmdir(f Fs) error {
|
||||||
|
err := TryRmdir(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Stats.Error()
|
Stats.Error()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
return err
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Purge removes a container and all of its contents
|
// Purge removes a container and all of its contents
|
||||||
|
@ -712,6 +712,7 @@ func TestServerSideMove(t *testing.T) {
|
|||||||
fstest.CheckItems(t, fremoteMove, file2)
|
fstest.CheckItems(t, fremoteMove, file2)
|
||||||
|
|
||||||
// Do server side move
|
// Do server side move
|
||||||
|
fs.Stats.ResetCounters()
|
||||||
err = fs.MoveDir(fremoteMove, r.fremote)
|
err = fs.MoveDir(fremoteMove, r.fremote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Server Side Move failed: %v", err)
|
t.Fatalf("Server Side Move failed: %v", err)
|
||||||
@ -721,6 +722,7 @@ func TestServerSideMove(t *testing.T) {
|
|||||||
fstest.CheckItems(t, fremoteMove, file2, file1)
|
fstest.CheckItems(t, fremoteMove, file2, file1)
|
||||||
|
|
||||||
// Move it back again, dst does not exist this time
|
// Move it back again, dst does not exist this time
|
||||||
|
fs.Stats.ResetCounters()
|
||||||
err = fs.MoveDir(r.fremote, fremoteMove)
|
err = fs.MoveDir(r.fremote, fremoteMove)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Server Side Move 2 failed: %v", err)
|
t.Fatalf("Server Side Move 2 failed: %v", err)
|
||||||
|
Loading…
Reference in New Issue
Block a user