22

Why is it that File.Move(sourceFileName, destFileName) works fine when the source file and destination files are in different partitions, but Directory.Move(sourceDirName, destDirName) don't? It throws

System.IO.IOException: "Source and destination path must have identical roots. Move will not work across volumes."

I even tried to create a DirectoryInfo instance and use the MoveTo(destDirName) method but without success.

Am I missing something? Do I really have to implement a "move" functionality myself? (the directory I want to move is very large btw).

first timer
  • 723
  • 1
  • 7
  • 17
  • 1
    Its because it uses this native API: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365239%28v=vs.85%29.aspx ***The one caveat is that the MoveFile function will fail on directory moves when the destination is on a different volume.*** I would `Process.Start` XCopy and redirect standard output to monitor the process, especially with large directories. – Ron Beyer May 04 '15 at 03:07
  • 1
    I see it as a probable implementation oversight that `File.Move` does work, but `Directory.Move` doesn't. – Marc.2377 Jul 19 '19 at 07:09

8 Answers8

13

You should Use Copy Function followed by a remove. As Move only works in the same drive. Directory.Move has a condition that states that :

IO Exception will be thrown if an attempt was made to move a directory to a different volume.

Ehsan Sajjad
  • 61,834
  • 16
  • 105
  • 160
Ehsan
  • 31,833
  • 6
  • 56
  • 65
6

Another option is, 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
  • I tried it and it didn't preserve the creation date, so I'm guessing it's still doing a copy/delete behind the scenes. – Kyle Delaney Jul 14 '17 at 22:59
3

Although this is not a Vb.Net question but I found no one mentioned this method so I think might help... Only you need to convert it to C# if needed.

Code:

My.Computer.FileSystem.MoveDirectory(SrcDir,DestDir) 

This works on different volume seamlessly/ per my experience.

3

Based on the posts "Copy a directory to a different drive" and "Non-recursive way to get all files in a directory and its subdirectories in Java", I wrote this non-recursive method and it works fine:

public static void Move(string source, string target)
    {
        if (!Directory.Exists(source))
        {
            throw new System.IO.DirectoryNotFoundException("Source directory couldn't be found.");
        }

        if (Directory.Exists(target))
        {
            throw new System.IO.IOException("Target directory already exists.");
        }

        DirectoryInfo sourceInfo = Directory.CreateDirectory(source);
        DirectoryInfo targetInfo = Directory.CreateDirectory(target);

        if (sourceInfo.FullName == targetInfo.FullName)
        {
            throw new System.IO.IOException("Source and target directories are the same.");
        }

        Stack<DirectoryInfo> sourceDirectories = new Stack<DirectoryInfo>();
        sourceDirectories.Push(sourceInfo);

        Stack<DirectoryInfo> targetDirectories = new Stack<DirectoryInfo>();
        targetDirectories.Push(targetInfo);

        while (sourceDirectories.Count > 0)
        {
            DirectoryInfo sourceDirectory = sourceDirectories.Pop();
            DirectoryInfo targetDirectory = targetDirectories.Pop();

            foreach (FileInfo file in sourceDirectory.GetFiles())
            {
                file.CopyTo(Path.Combine(targetDirectory.FullName, file.Name), overwrite: true);
            }

            foreach(DirectoryInfo subDirectory in sourceDirectory.GetDirectories())
            {
                sourceDirectories.Push(subDirectory);
                targetDirectories.Push(targetDirectory.CreateSubdirectory(subDirectory.Name));
            }
        }

        sourceInfo.Delete(true);
    }
L.Lara
  • 31
  • 2
  • Beautiful work there. Works out of the box, but had to comment the ```if (Directory.Exists(target)) { throw new System.IO.IOException("Target directory already exists."); }``` in my case – Egil Sandfeld Aug 12 '22 at 09:25
2

You can also p/invoke SHFileOperation which is the same function Windows Explorer uses to move directories around. It will either perform a true move or recursive-copy-then-delete, as appropriate.

It can also show the same progress UI as explorer, just by setting a flag.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
1

I know this post is a little old... but there is a way around this! Don't try and move the directory, but zip it up and move it as a File.Move(src,dest); and you can then extract it and there you have it!

Alex
  • 11
  • 1
  • It is unlikely you will end up getting any votes for this suggestion. This answer already has an accepted answer. Your proposed solution has the same issues as other answers but with more complexity – brianfeucht Jun 20 '18 at 15:13
  • +1 because the directory creation dates are preserved using this approach. At least when tested using 7z. – 2b77bee6-5445-4c77-b1eb-4df3e5 Sep 21 '18 at 13:02
0

I had same problem in VB.NET and instead of "Directory.Move" I used MoveFolder with "FileSystemObject". You can preserve creation dates with this method.

Scripting.FileSystemObject oFSO = new Scripting.FileSystemObject();
oFSO.MoveFolder(sourceDirName, destDirName)
CodeCatia
  • 127
  • 1
  • 9
0

i have this problem to and i like to solve it in this way

 string startPath = @".\start";
        string zipPath = @".\result.zip";
        string extractPath = @".\extract";

        ZipFile.CreateFromDirectory(startPath, zipPath);

        ZipFile.ExtractToDirectory(zipPath, extractPath);
hossein sedighian
  • 1,711
  • 1
  • 13
  • 16