2010-03-31 138 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); 
相關問題