Скопируйте все содержимое каталога в C #

Я хочу скопировать все содержимое каталога из одного места в другое в C #.

Кажется, что нет способа сделать это, используя classы System.IO без большой рекурсии.

В VB существует метод, который мы можем использовать, если добавить ссылку на Microsoft.VisualBasic :

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

Это кажется довольно уродливым взломом. Есть ли способ лучше?

Намного легче

 //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); 

Хм, я думаю, что неправильно понимаю вопрос, но я буду рисковать. Что случилось со следующим простым методом?

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

EDIT Поскольку эта публикация собрала внушительное количество downvotes для такого простого ответа на столь же простой вопрос, позвольте мне добавить объяснение. Пожалуйста, прочитайте это, прежде чем начинать .

Прежде всего, этот код не предназначен для замены кода в вопросе. Это только для иллюстрации.

Microsoft.VisualBasic.Devices.Computer.FileSystem.CopyDirectory выполняет некоторые дополнительные проверки правильности (например, являются ли источники и цель действительными каталогами, является ли источник родителем объекта и т. Д.), Которые отсутствуют в этом ответе. Этот код, вероятно, также более оптимизирован.

Тем не менее, код работает хорошо . Он (почти идентично) использовался в зрелом программном обеспечении в течение многих лет. Помимо неотъемлемой изменчивости, присутствующей во всех манипуляциях ввода-вывода (например, что произойдет, если пользователь вручную отключит USB-накопитель, пока ваш код пишет к нему?), Нет известных проблем.

В частности, я хотел бы отметить, что использование рекурсии здесь абсолютно не проблема. Ни в теории (концептуально, это самое элегантное решение), ни на практике: этот код не будет переполнять стек . Стек достаточно велик, чтобы обрабатывать даже глубоко вложенные иерархии файлов. Задолго до того, как пространство стека станет проблемой, удаляется ограничение длины пути к папке.

Обратите внимание, что злоумышленник может нарушить это предположение, используя глубоко вложенные каталоги по одной букве. Я этого не пробовал. Но просто для того, чтобы проиллюстрировать суть: для того, чтобы этот переполнение кода на типичном компьютере, каталоги должны были быть вложены несколько тысяч раз. Это просто не реалистичный сценарий.

Скопировано из 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. } 

Попробуй это:

 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(); 

Ваши аргументы xcopy могут отличаться, но вы получаете эту идею.

Или, если вы хотите идти сложным способом, добавьте ссылку на свой проект для Microsoft.VisualBasic, а затем используйте следующее:

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

Однако использование одной из рекурсивных функций – лучший способ, так как ему не придется загружать dll VB.

Этот сайт всегда помогал мне много, и теперь моя очередь помогать другим в том, что я знаю.

Я надеюсь, что мой код ниже будет полезен для кого-то.

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

Скопируйте папку рекурсивно без рекурсии, чтобы избежать переполнения стека.

 public static void CopyDirectory(string source, string target) { var stack = new Stack(); 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; } } 

Вот class утилиты, который я использовал для задач ввода-вывода, подобных этому.

 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 

Небольшое улучшение в ответе d4nt, поскольку вы, вероятно, хотите проверить наличие ошибок и не должны изменять пути xcopy, если работаете на сервере и машине разработки:

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

Если вам нравится популярный ответ Konrad, но вы хотите, чтобы source был папкой под target , а не помещал ее под target папкой, вот код для этого. Он возвращает вновь созданный DirectoryInfo , который удобен:

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

Вы всегда можете использовать это , взятое с веб-сайта Microsoft.

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

tboswell заменяет версию Proof (которая устойчива к повторению шаблона в пути к файлу)

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

Возможно, это не относится к производительности, но я использую его для 30 МБ папок, и он работает безупречно. Кроме того, мне не понравился весь объем кода и recursion, необходимые для такой простой задачи.

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

Примечание. ZipFile доступен в .NET 4.5+ в пространстве имен System.IO.Compression

Извините за предыдущий код, у него все еще были ошибки 🙁 (стал жертвой самой быстрой проблемы с пистолетом). Здесь он протестирован и работает. Ключ – это SearchOption.AllDirectories, который устраняет необходимость в явной рекурсии.

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

Это мой код, надеюсь, эта помощь

  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 files = GetAllFileAndFolder(source); foreach (string file in files) { KCOPY(file, target); } } } private List GetAllFileAndFolder(string path) { List allFile = new List(); 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; } 

Ниже приведен метод расширения для DirectoryInfo a la FileInfo.CopyTo (обратите внимание на параметр 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; } 

Лучше, чем любой код (метод расширения для DirectoryInfo с рекурсией)

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

Используйте этот class.

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

Один вариант с одним контуром для копирования всех папок и файлов:

 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); } 
  • быстрое преобразование Bitmap в BitmapSource wpf
  • Скопируйте несколько столбцов csv-файла в таблицу
  • Как скопировать файл в банку за пределы банки?
  • Как скопировать массив символов в C?
  • Скопируйте cv :: Mat внутри ROI другого
  • Почему Reinterpret_cast Force copy_n не используется для трансляции между одинаковыми размерами?
  • Как скопировать одну карту в другую с помощью std :: copy?
  • Interesting Posts

    Быстрый способ установки win7 и программ на многие новые мини-ПК без OSless, которые будут подключены в локальной сети

    Лучший XML-парсер для Java

    Управление WebBrowser в новом streamе

    Принудительное использование плавающей запятой в .NET?

    Форсировать текст / цвет фона в раскрывающемся меню в Firefox.

    Подclass classа Sparql или EquivalentTo

    Почему размер кеша L1 не сильно увеличился за последние 20 лет?

    Насколько хорошо поддерживается Unicode в C ++ 11?

    Как использовать элемент управления WebBrowser Событие DocumentCompleted в C #?

    Отправьте данные обратно в скрипт, который начал работу с помощью оболочки adb am start

    Подключение ноутбука к телевизору через HDMI

    Как узнать, сколько хостов находится в маске подсети: 255.255.255.252?

    Синхронизация по целочисленному значению

    Linux снимок экрана, который сохраняет снимки напрямую, не запрашивая имя файла

    jQuery scrollTop не работает в Chrome, но работает в Firefox

    Давайте будем гением компьютера.