ruta reemplazar obtener nombre manipular guardar directorios directorio carpeta buscar archivos archivo c# .net copy

reemplazar - obtener ruta de un archivo c#



Copie todo el contenido de un directorio en C# (19)

Quiero copiar todo el contenido de un directorio de una ubicación a otra en C #.

No parece haber una manera de hacer esto usando las clases de System.IO sin mucha recursión.

Hay un método en VB que podemos usar si agregamos una referencia a Microsoft.VisualBasic :

new Microsoft.VisualBasic.Devices.Computer(). FileSystem.CopyDirectory( sourceFolder, outputFolder );

Esto parece un truco bastante feo. ¿Hay alguna manera mejor?


Aquí hay un método de extensión para DirectoryInfo a la FileInfo.CopyTo (tenga en cuenta el parámetro de overwrite ):

public static DirectoryInfo CopyTo(this DirectoryInfo sourceDir, string destinationPath, bool overwrite = false) { var sourcePath = sourceDir.FullName; var destination = new DirectoryInfo(destinationPath); destination.Create(); foreach (var sourceSubDirPath in Directory.EnumerateDirectories(sourcePath, "*", SearchOption.AllDirectories)) Directory.CreateDirectory(sourceSubDirPath.Replace(sourcePath, destinationPath)); foreach (var file in Directory.EnumerateFiles(sourcePath, "*", SearchOption.AllDirectories)) File.Copy(file, file.Replace(sourcePath, destinationPath), overwrite); return destination; }


Aquí hay una clase de utilidad que he usado para tareas de IO como esta.

using System; using System.Runtime.InteropServices; namespace MyNameSpace { public class ShellFileOperation { private static String StringArrayToMultiString(String[] stringArray) { String multiString = ""; if (stringArray == null) return ""; for (int i=0 ; i<stringArray.Length ; i++) multiString += stringArray[i] + ''/0''; multiString += ''/0''; return multiString; } public static bool Copy(string source, string dest) { return Copy(new String[] { source }, new String[] { dest }); } public static bool Copy(String[] source, String[] dest) { Win32.SHFILEOPSTRUCT FileOpStruct = new Win32.SHFILEOPSTRUCT(); FileOpStruct.hwnd = IntPtr.Zero; FileOpStruct.wFunc = (uint)Win32.FO_COPY; String multiSource = StringArrayToMultiString(source); String multiDest = StringArrayToMultiString(dest); FileOpStruct.pFrom = Marshal.StringToHGlobalUni(multiSource); FileOpStruct.pTo = Marshal.StringToHGlobalUni(multiDest); FileOpStruct.fFlags = (ushort)Win32.ShellFileOperationFlags.FOF_NOCONFIRMATION; FileOpStruct.lpszProgressTitle = ""; FileOpStruct.fAnyOperationsAborted = 0; FileOpStruct.hNameMappings = IntPtr.Zero; int retval = Win32.SHFileOperation(ref FileOpStruct); if(retval != 0) return false; return true; } public static bool Move(string source, string dest) { return Move(new String[] { source }, new String[] { dest }); } public static bool Delete(string file) { Win32.SHFILEOPSTRUCT FileOpStruct = new Win32.SHFILEOPSTRUCT(); FileOpStruct.hwnd = IntPtr.Zero; FileOpStruct.wFunc = (uint)Win32.FO_DELETE; String multiSource = StringArrayToMultiString(new string[] { file }); FileOpStruct.pFrom = Marshal.StringToHGlobalUni(multiSource); FileOpStruct.pTo = IntPtr.Zero; FileOpStruct.fFlags = (ushort)Win32.ShellFileOperationFlags.FOF_SILENT | (ushort)Win32.ShellFileOperationFlags.FOF_NOCONFIRMATION | (ushort)Win32.ShellFileOperationFlags.FOF_NOERRORUI | (ushort)Win32.ShellFileOperationFlags.FOF_NOCONFIRMMKDIR; FileOpStruct.lpszProgressTitle = ""; FileOpStruct.fAnyOperationsAborted = 0; FileOpStruct.hNameMappings = IntPtr.Zero; int retval = Win32.SHFileOperation(ref FileOpStruct); if(retval != 0) return false; return true; } public static bool Move(String[] source, String[] dest) { Win32.SHFILEOPSTRUCT FileOpStruct = new Win32.SHFILEOPSTRUCT(); FileOpStruct.hwnd = IntPtr.Zero; FileOpStruct.wFunc = (uint)Win32.FO_MOVE; String multiSource = StringArrayToMultiString(source); String multiDest = StringArrayToMultiString(dest); FileOpStruct.pFrom = Marshal.StringToHGlobalUni(multiSource); FileOpStruct.pTo = Marshal.StringToHGlobalUni(multiDest); FileOpStruct.fFlags = (ushort)Win32.ShellFileOperationFlags.FOF_NOCONFIRMATION; FileOpStruct.lpszProgressTitle = ""; FileOpStruct.fAnyOperationsAborted = 0; FileOpStruct.hNameMappings = IntPtr.Zero; int retval = Win32.SHFileOperation(ref FileOpStruct); if(retval != 0) return false; return true; } } }


Copiado de MSDN :

using System; using System.IO; class CopyDir { public static void Copy(string sourceDirectory, string targetDirectory) { DirectoryInfo diSource = new DirectoryInfo(sourceDirectory); DirectoryInfo diTarget = new DirectoryInfo(targetDirectory); CopyAll(diSource, diTarget); } public static void CopyAll(DirectoryInfo source, DirectoryInfo target) { Directory.CreateDirectory(target.FullName); // Copy each file into the new directory. foreach (FileInfo fi in source.GetFiles()) { Console.WriteLine(@"Copying {0}/{1}", target.FullName, fi.Name); fi.CopyTo(Path.Combine(target.FullName, fi.Name), true); } // Copy each subdirectory using recursion. foreach (DirectoryInfo diSourceSubDir in source.GetDirectories()) { DirectoryInfo nextTargetSubDir = target.CreateSubdirectory(diSourceSubDir.Name); CopyAll(diSourceSubDir, nextTargetSubDir); } } public static void Main() { string sourceDirectory = @"c:/sourceDirectory"; string targetDirectory = @"c:/targetDirectory"; Copy(sourceDirectory, targetDirectory); } // Output will vary based on the contents of the source directory. }


Copie la carpeta recursivamente sin recursividad para evitar el desbordamiento de pila.

public static void CopyDirectory(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, "*.*")) { File.Copy(file, Path.Combine(folders.Target, Path.GetFileName(file))); } foreach (var folder in Directory.GetDirectories(folders.Source)) { stack.Push(new Folders(folder, Path.Combine(folders.Target, Path.GetFileName(folder)))); } } } 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; } }


Este es mi código espero que esta ayuda.

private void KCOPY(string source, string destination) { if (IsFile(source)) { string target = Path.Combine(destination, Path.GetFileName(source)); File.Copy(source, target, true); } else { string fileName = Path.GetFileName(source); string target = System.IO.Path.Combine(destination, fileName); if (!System.IO.Directory.Exists(target)) { System.IO.Directory.CreateDirectory(target); } List<string> files = GetAllFileAndFolder(source); foreach (string file in files) { KCOPY(file, target); } } } private List<string> GetAllFileAndFolder(string path) { List<string> allFile = new List<string>(); foreach (string dir in Directory.GetDirectories(path)) { allFile.Add(dir); } foreach (string file in Directory.GetFiles(path)) { allFile.Add(file); } return allFile; } private bool IsFile(string path) { if ((File.GetAttributes(path) & FileAttributes.Directory) == FileAttributes.Directory) { return false; } return true; }


Este sitio siempre me ha ayudado mucho, y ahora es mi turno de ayudar a los demás con lo que sé.

Espero que mi código de abajo sea útil para alguien.

string source_dir = @"E:/"; string destination_dir = @"C:/"; // substring is to remove destination_dir absolute path (E:/). // Create subdirectory structure in destination foreach (string dir in System.IO.Directory.GetDirectories(source_dir, "*", System.IO.SearchOption.AllDirectories)) { System.IO.Directory.CreateDirectory(System.IO.Path.Combine(destination_dir, dir.Substring(source_dir.Length + 1))); // Example: // > C:/sources (and not C:/E:/sources) } foreach (string file_name in System.IO.Directory.GetFiles(source_dir, "*", System.IO.SearchOption.AllDirectories)) { System.IO.File.Copy(file_name, System.IO.Path.Combine(destination_dir, file_name.Substring(source_dir.Length + 1))); }


Hmm, creo que no entiendo la pregunta pero voy a arriesgarme. ¿Qué hay de malo con el siguiente método directo?

public static void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target) { foreach (DirectoryInfo dir in source.GetDirectories()) CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name)); foreach (FileInfo file in source.GetFiles()) file.CopyTo(Path.Combine(target.FullName, file.Name)); }

EDITAR Debido a que esta publicación ha generado un número impresionante de votos negativos para una respuesta tan simple a una pregunta igualmente simple, permítame agregar una explicación. Por favor lea esto antes de votar .

En primer lugar, este código no pretende ser un reemplazo directo del código en la pregunta. Es sólo para fines ilustrativos.

Microsoft.VisualBasic.Devices.Computer.FileSystem.CopyDirectory realiza algunas pruebas de corrección adicionales (por ejemplo, si el origen y el destino son directorios válidos, si el origen es un padre del objetivo, etc.) que faltan en esta respuesta. Ese código es probablemente también más optimizado.

Dicho esto, el código funciona bien . Se ha utilizado (casi de manera idéntica) en un software maduro durante años. Aparte de la inestabilidad inherente presente con todas las manipulaciones de IO (por ejemplo, ¿qué sucede si el usuario desconecta manualmente la unidad USB mientras su código está escribiendo en ella?), No hay problemas conocidos.

En particular, me gustaría señalar que el uso de la recursión aquí no es absolutamente un problema. Ni en teoría (conceptualmente, es la solución más elegante) ni en la práctica: este código no desbordará la pila . La pila es lo suficientemente grande como para manejar jerarquías de archivos incluso profundamente anidadas. Mucho antes de que el espacio de la pila se convierta en un problema, se activa la limitación de longitud de la ruta de la carpeta.

Tenga en cuenta que un usuario malintencionado podría romper esta suposición utilizando directorios profundamente anidados de una letra cada uno. No he probado esto. Pero solo para ilustrar el punto: para hacer que este código se desborde en una computadora típica, los directorios tendrían que estar anidados unos pocos miles de veces. Esto simplemente no es un escenario realista.


La versión Proof de reemplazo de tboswell (que es resistente al patrón de repetición en filepath)

public static void copyAll(string SourcePath , string DestinationPath ) { //Now Create all of the directories foreach (string dirPath in Directory.GetDirectories(SourcePath, "*", SearchOption.AllDirectories)) Directory.CreateDirectory(Path.Combine(DestinationPath ,dirPath.Remove(0, SourcePath.Length )) ); //Copy all the files & Replaces any files with the same name foreach (string newPath in Directory.GetFiles(SourcePath, "*.*", SearchOption.AllDirectories)) File.Copy(newPath, Path.Combine(DestinationPath , newPath.Remove(0, SourcePath.Length)) , true); }


Lo siento por el código anterior, todavía tenía errores :( (cayó presa del problema del arma más rápida). Aquí está probado y funcionando. La clave es SearchOption.AllDirectories, que elimina la necesidad de una recursión explícita.

string path = "C://a"; string[] dirs = Directory.GetDirectories(path, "*.*", SearchOption.AllDirectories); string newpath = "C://x"; try { Directory.CreateDirectory(newpath); } catch (IOException ex) { Console.WriteLine(ex.Message); } for (int j = 0; j < dirs.Length; j++) { try { Directory.CreateDirectory(dirs[j].Replace(path, newpath)); } catch (IOException ex) { Console.WriteLine(ex.Message); } } string[] files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories); for (int j = 0; j < files.Length; j++) { try { File.Copy(files[j], files[j].Replace(path, newpath)); } catch (IOException ex) { Console.WriteLine(ex.Message); } }


Más fácil

//Now Create all of the directories foreach (string dirPath in Directory.GetDirectories(SourcePath, "*", SearchOption.AllDirectories)) Directory.CreateDirectory(dirPath.Replace(SourcePath, DestinationPath)); //Copy all the files & Replaces any files with the same name foreach (string newPath in Directory.GetFiles(SourcePath, "*.*", SearchOption.AllDirectories)) File.Copy(newPath, newPath.Replace(SourcePath, DestinationPath), true);


Mejor que cualquier código (método de extensión a DirectoryInfo con recursión)

public static bool CopyTo(this DirectoryInfo source, string destination) { try { foreach (string dirPath in Directory.GetDirectories(source.FullName)) { var newDirPath = dirPath.Replace(source.FullName, destination); Directory.CreateDirectory(newDirPath); new DirectoryInfo(dirPath).CopyTo(newDirPath); } //Copy all the files & Replaces any files with the same name foreach (string filePath in Directory.GetFiles(source.FullName)) { File.Copy(filePath, filePath.Replace(source.FullName,destination), true); } return true; } catch (IOException exp) { return false; } }


O, si quieres ir por el camino difícil, agrega una referencia a tu proyecto para Microsoft.VisualBasic y luego usa lo siguiente:

Microsoft.VisualBasic.FileIO.FileSystem.CopyDirectory(fromDirectory, toDirectory);

Sin embargo, usar una de las funciones recursivas es una mejor manera de hacerlo, ya que no tendrá que cargar la DLL de VB.


Prueba esto:

Process proc = new Process(); proc.StartInfo.UseShellExecute = true; proc.StartInfo.FileName = Path.Combine(Environment.SystemDirectory, "xcopy.exe"); proc.StartInfo.Arguments = @"C:/source C:/destination /E /I"; proc.Start();

Tus argumentos de xcopy pueden variar pero entiendes la idea.


Puede que no sea consciente del rendimiento, pero lo estoy usando para carpetas de 30 MB y funciona perfectamente. Además, no me gustó toda la cantidad de código y la recursión requerida para una tarea tan fácil.

var source_folder = "c:/src"; var dest_folder = "c:/dest"; var zipFile = source_folder + ".zip"; ZipFile.CreateFromDirectory(source_folder, zipFile); ZipFile.ExtractToDirectory(zipFile, dest_folder); File.Delete(zipFile);

Nota: ZipFile está disponible en .NET 4.5+ en el espacio de nombres System.IO.Compression


Si te gusta la popular respuesta de Konrad, pero quieres que la source sí sea una carpeta debajo del target , en lugar de poner a sus hijos debajo de la carpeta target , aquí está el código para eso. Devuelve el DirectoryInfo recién creado, que es útil:

public static DirectoryInfo CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target) { var newDirectoryInfo = target.CreateSubdirectory(source.Name); foreach (var fileInfo in source.GetFiles()) fileInfo.CopyTo(Path.Combine(newDirectoryInfo.FullName, fileInfo.Name)); foreach (var childDirectoryInfo in source.GetDirectories()) CopyFilesRecursively(childDirectoryInfo, newDirectoryInfo); return newDirectoryInfo; }


Siempre puedes usar this , tomado del sitio web de Microsofts.

static void Main() { // Copy from the current directory, include subdirectories. DirectoryCopy(".", @"./temp", true); } private static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs) { // Get the subdirectories for the specified directory. DirectoryInfo dir = new DirectoryInfo(sourceDirName); if (!dir.Exists) { throw new DirectoryNotFoundException( "Source directory does not exist or could not be found: " + sourceDirName); } DirectoryInfo[] dirs = dir.GetDirectories(); // If the destination directory doesn''t exist, create it. if (!Directory.Exists(destDirName)) { Directory.CreateDirectory(destDirName); } // Get the files in the directory and copy them to the new location. FileInfo[] files = dir.GetFiles(); foreach (FileInfo file in files) { string temppath = Path.Combine(destDirName, file.Name); file.CopyTo(temppath, false); } // If copying subdirectories, copy them and their contents to new location. if (copySubDirs) { foreach (DirectoryInfo subdir in dirs) { string temppath = Path.Combine(destDirName, subdir.Name); DirectoryCopy(subdir.FullName, temppath, copySubDirs); } } }


Una pequeña mejora en la respuesta de d4nt, ya que probablemente desee verificar errores y no tener que cambiar las rutas de xcopy si está trabajando en un servidor y una máquina de desarrollo:

public void CopyFolder(string source, string destination) { string xcopyPath = Environment.GetEnvironmentVariable("WINDIR") + @"/System32/xcopy.exe"; ProcessStartInfo info = new ProcessStartInfo(xcopyPath); info.UseShellExecute = false; info.RedirectStandardOutput = true; info.Arguments = string.Format("/"{0}/" /"{1}/" /E /I", source, destination); Process process = Process.Start(info); process.WaitForExit(); string result = process.StandardOutput.ReadToEnd(); if (process.ExitCode != 0) { // Or your own custom exception, or just return false if you prefer. throw new InvalidOperationException(string.Format("Failed to copy {0} to {1}: {2}", source, destination, result)); } }


Una variante con un solo bucle para copiar todas las carpetas y archivos:

foreach (var f in Directory.GetFileSystemEntries(path, "*", SearchOption.AllDirectories)) { var output = Regex.Replace(f, @"^" + path, newPath); if (File.Exists(f)) File.Copy(f, output, true); else Directory.CreateDirectory(output); }


Usa esta clase.

public static class Extensions { public static void CopyTo(this DirectoryInfo source, DirectoryInfo target, bool overwiteFiles = true) { if (!source.Exists) return; if (!target.Exists) target.Create(); Parallel.ForEach(source.GetDirectories(), (sourceChildDirectory) => CopyTo(sourceChildDirectory, new DirectoryInfo(Path.Combine(target.FullName, sourceChildDirectory.Name)))); foreach (var sourceFile in source.GetFiles()) sourceFile.CopyTo(Path.Combine(target.FullName, sourceFile.Name), overwiteFiles); } public static void CopyTo(this DirectoryInfo source, string target, bool overwiteFiles = true) { CopyTo(source, new DirectoryInfo(target), overwiteFiles); } }