2010-03-31 21 views
16

Tengo carpeta principal:Directory.Move no funciona (ya existen archivos)

c:\test 

Y no tengo 2 carpetas: Las películas y fotografías.

Fotos tiene tres carpetas con archivos con la misma estructura: Personas, Animales y Edificios. Estoy tratando este código:

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

me sale excepción:

File already exists 

Respuesta

31

Este método moverá el contenido de una carpeta recursivamente y sobrescribirá los archivos existentes.
Debe agregar un poco de manejo de excepciones.
Editar:
Este método se implementa con un ciclo while y una pila en lugar de recursión.

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; 
    } 
} 

Actualización:
Esta es una versión más sencilla con el uso de Directory.EnumerateFiles de forma recursiva en lugar de utilizar una pila.
Esto solo funcionará con .net 4 o posterior, para nosotros con una versión anterior de .net change Directory.EnumerateFiles a 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

Una gran solución que mejora mucho en el bastante incorporado. –

+0

¿Por qué este método es mejor que la recursión? – Daniel

+0

El problema que veo es que el archivo está bloqueado durante la copia y está disponible al final de Directory.Delete (source, true) lo eliminará. – Daniel

7

El directorio de destino no debe existir ya - el método Directory.Move crea el directorio de destino para usted.

0

¿Es seguro borrar la carpeta de destino antes de copiar contenido nuevo en ella?

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

Unfortunalety not ... – user278618

0

Los más comunes 2 razones por las Directory.Move podrían fallar son, si:

  • Es un volumen diferente (es necesario copiar/eliminar)
  • Ya existe (no soporta sobreescritura por defecto)

Aquí está mi solución simple para el segundo problema (sobrescribir):

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

Este código tiene el problema de que si Move (destDirName, tmpDir) falla, entonces se lanzará una excepción en Delete (tmpDir). –

+0

¿No hay una forma incorporada para que C# realice esta acción común de Windows? –

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