2010-03-31 4 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; 
    } 
} 

Update:
Это более простой вариант с использованием Directory.EnumerateFiles рекурсивно вместо того, чтобы использовать стек.
Это будет работать только с .net 4 или новее, нам с более ранней версией .net change Directory.EnumerateFiles to Directory.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

Отличное решение, которое значительно улучшается на довольно тонком встроенном. –

+0

Почему этот метод лучше, чем рекурсия? – Daniel

+0

Проблема, которую я вижу, заключается в том, что файл заблокирован во время копирования и становится доступным в самом конце Directory.Delete (source, true) удалит его. – Daniel

7

каталог назначения не должен уже существовать - метод Directory.Move создает каталог назначения для вас.

0

Безопасно ли вы удалить папку назначения, прежде чем копировать в нее новое содержимое?

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

Unfortunalety not ... – user278618

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) терпит неудачу, тогда исключение будет выведено, наконец, Delete (tmpDir). –

+0

Нет ли встроенного способа для C# для выполнения этого обычного действия Windows? –

1
ProcessStartInfo p = new ProcessStartInfo("cmd", "/c move \"c:\\test\\Movies\" \"c:\\test\Test\\""); 
p.WindowStyle = ProcessWindowStyle.Hidden; //hide mode 
Process.Start(p); 
Смежные вопросы