5

Apparently I can't move files on different volumes using Directory.Move.

I have read that I have to copy each file individually to the destination, then delete the source directory.

Do I have any other option?

Blankman
  • 259,732
  • 324
  • 769
  • 1,199

4 Answers4

6

Regardless of whether or not Directory.Move (or any other function) performed the move between volumes, it would essentially be doing a copy and delete anyway underneath. So if you want a speed increase, that's not going to happen. I think the best solution would be to write your own reusable move function, which would get the volume label (C:,D:) from the to and from paths, and then either perform a move, or copy+delete when necessary.

Kibbee
  • 65,369
  • 27
  • 142
  • 182
4

To my knowledge there is no other way however deleting a directory has a catch: Read Only Files might cause a UnauthorizedAccessException when deleting a directory and all of its contents.

This recurses a directory and unsets all the read only flags. Call before Directory.Delete:

public void removeReadOnlyDeep(string directory)
{
    string[] files = Directory.GetFiles(directory);
    foreach (string file in files)
    {
        FileAttributes attributes = File.GetAttributes(file);
        if ((attributes & FileAttributes.ReadOnly) != 0)
        {
            File.SetAttributes(file, ~FileAttributes.ReadOnly);
        }
    }
    string[] dirs = Directory.GetDirectories(directory);
    foreach (string dir in dirs)
    {
        removeReadOnlyDeep(dir);
    }
}
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Martijn Laarman
  • 13,476
  • 44
  • 63
3

An easier option would be, to add a reference to the Microsoft.VisualBasic namespace and use the MoveDirectory method, which can move across volumes.

Microsoft.VisualBasic.FileIO.FileSystem.MoveDirectory(sourceDirName, destDirName);
NePh
  • 966
  • 9
  • 21
0

Try to use this:

public static void RobustMove(string sourceDirectory, string destDirectory)
{
    //move if directories are on the same volume
    if (Path.GetPathRoot(source) == Path.GetPathRoot(destination))
    {
        Directory.Move(source, destination);
    }
    else
    {        
        CopyDirectoryRecursive(source, destination);
        Directory.Delete(source, true);
    }
}

You will find CopyDirectoryRecursive function here:

This should be working until you use spanned volume or symbol links to another physical disk.

To be even more robust you can improve this function to use Move until System.IO .Exception is thrown and then to switch to copying and deleting.

Tomas Kubes
  • 23,880
  • 18
  • 111
  • 148