2010-03-31 83 views
16

我有主文件夹:Directory.Move不工作(文件已经存在)

c:\test 

在那里我有2个文件夹:电影和照片。

照片有三个具有相同结构的文件夹:人物,动物和建筑物。我想这样的代码:

Directory.Move(@"c:\test\Movies", @"c:\test\Test"); 

我得到异常:

File already exists 

回答

31

该方法将递归地移动文件夹的内容并覆盖现有文件。
您应该添加一些异常处理。
编辑:
此方法使用while循环和堆栈实现,而不是递归。

public static void MoveDirectory(string source, string target) 
{ 
    var stack = new Stack<Folders>(); 
    stack.Push(new Folders(source, target)); 

    while (stack.Count > 0) 
    { 
     var folders = stack.Pop(); 
     Directory.CreateDirectory(folders.Target); 
     foreach (var file in Directory.GetFiles(folders.Source, "*.*")) 
     { 
      string targetFile = Path.Combine(folders.Target, Path.GetFileName(file)); 
      if (File.Exists(targetFile)) File.Delete(targetFile); 
      File.Move(file, targetFile); 
     } 

     foreach (var folder in Directory.GetDirectories(folders.Source)) 
     { 
      stack.Push(new Folders(folder, Path.Combine(folders.Target, Path.GetFileName(folder)))); 
     } 
    } 
    Directory.Delete(source, true); 
} 
public class Folders 
{ 
    public string Source { get; private set; } 
    public string Target { get; private set; } 

    public Folders(string source, string target) 
    { 
     Source = source; 
     Target = target; 
    } 
} 

更新:
这是一个简单的版本与使用Directory.EnumerateFiles递归而不是使用堆栈。
这只适用于.net 4或更高版本,使用早期版本的.net更改Directory.EnumerateFilesDirectory.GetFiles

public static void MoveDirectory(string source, string target) 
{ 
    var sourcePath = source.TrimEnd('\\', ' '); 
    var targetPath = target.TrimEnd('\\', ' '); 
    var files = Directory.EnumerateFiles(sourcePath, "*", SearchOption.AllDirectories) 
         .GroupBy(s=> Path.GetDirectoryName(s)); 
    foreach (var folder in files) 
    { 
     var targetFolder = folder.Key.Replace(sourcePath, targetPath); 
     Directory.CreateDirectory(targetFolder); 
     foreach (var file in folder) 
     { 
      var targetFile = Path.Combine(targetFolder, Path.GetFileName(file)); 
      if (File.Exists(targetFile)) File.Delete(targetFile); 
      File.Move(file, targetFile); 
     } 
    } 
    Directory.Delete(source, true); 
} 
+1

一个很好的解决方案,大大提高了相当简洁的内置一个。 – 2013-04-17 14:41:29

+0

这个方法为什么比递归更好? – Daniel 2014-01-19 22:40:11

+0

我看到的问题是它在复制过程中锁定文件并在最后变为可用Directory.Delete(source,true)将其删除。 – Daniel 2014-01-19 23:20:45

7

目标目录不应该已经存在 - 的Directory.Move方法为您创建的目标目录。

0

在将新内容复制到目标文件夹之前删除目标文件夹是否安全?

Directory.Delete(@"c:\test\test"); 
    Directory.Move(@"c:\test\movies",@"c:\test\test"); 
+0

不幸的不是... – user278618 2010-03-31 13:10:26

0

最常见的2个原因Directory.Move可能会失败的,如果:

  • 这是一个不同的卷(你需要复制/删除)
  • 它已经存在(不支持覆盖默认情况下)

这里是我的第二个问题简单的解决方案(覆盖):

public bool MoveDirectory(string sourceDirName, string destDirName, bool overwrite) 
{ 
    if (overwrite && Directory.Exists(destDirName)) 
    { 
     var needRestore = false; 
     var tmpDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); 
     try 
     { 
      Directory.Move(destDirName, tmpDir); 
      needRestore = true; // only if fails 
      Directory.Move(sourceDirName, destDirName); 
      return true; 
     } 
     catch (Exception) 
     { 
      if (needRestore) 
      { 
       Directory.Move(tmpDir, destDirName); 
      } 
     } 
     finally 
     { 
      Directory.Delete(tmpDir, true); 
     } 
    } 
    else 
    { 
     Directory.Move(sourceDirName, destDirName); // Can throw an Exception 
     return true; 
    } 
    return false; 
} 
+1

此代码存在如果Move(destDirName,tmpDir)失败,则会在最后删除(tmpDir)时抛出异常。 – 2015-02-19 11:14:25

+0

C#无法执行此常见Windows操作吗? – 2017-08-28 13:13:43

1
ProcessStartInfo p = new ProcessStartInfo("cmd", "/c move \"c:\\test\\Movies\" \"c:\\test\Test\\""); 
p.WindowStyle = ProcessWindowStyle.Hidden; //hide mode 
Process.Start(p); 
相关问题