Я хочу скопировать все содержимое каталога из одного места в другое в C #.
Кажется, нет способа сделать это с помощью System.IO
классов без большого количества рекурсии.
В VB есть метод, который мы можем использовать, если добавим ссылку на Microsoft.VisualBasic
:
new Microsoft.VisualBasic.Devices.Computer().
FileSystem.CopyDirectory( sourceFolder, outputFolder );
Это похоже на довольно уродливый хак. Есть ли способ лучше?
Microsoft.VisualBasic
и неSystem.IO
? Причина в том, что в Mono этого нет, в том, что все библиотеки, которые считаются «основными»,System.[something]
- все остальные - нет. У меня нет проблем со ссылками на дополнительную DLL, но есть веская причина, почему Microsoft не включила эту функцию вSystem.IO
.Ответы:
Намного легче
источник
Replace
имеет проблему, если у вас есть повторяющийся шаблон внутри пути, например,"sourceDir/things/sourceDir/things"
должен стать"destinationDir/things/sourceDir/things"
, но если вы используете замену, он становится"destinationDir/things/destinationDir/things"
*.*
вместо*
? Вы тоже не хотите копировать файлы без расширений?Хм, я думаю, что неправильно понял вопрос, но я собираюсь рискнуть. Что не так со следующим простым методом?
РЕДАКТИРОВАТЬ Так как эта публикация собрала впечатляющее количество голосов за такой простой ответ на столь же простой вопрос, позвольте мне добавить объяснение. Пожалуйста, прочитайте это до понижения .
Прежде всего, этот код не предназначен для замены кода, о котором идет речь. Это только для иллюстрации.
Microsoft.VisualBasic.Devices.Computer.FileSystem.CopyDirectory
выполняет некоторые дополнительные тесты на корректность (например, являются ли источник и цель действительными каталогами, является ли источник родителем цели и т. д.), которые отсутствуют в этом ответе. Этот код, вероятно, также более оптимизирован.Тем не менее, код работает хорошо . Он имеет (почти одинаково) был использован в зрелом программном обеспечении в течение многих лет. Помимо врожденной неустойчивости, присутствующей во всех обработках ввода-вывода (например, что произойдет, если пользователь вручную отключит USB-накопитель во время записи на него кода?), Нет известных проблем.
В частности, я хотел бы отметить, что использование рекурсии здесь абсолютно не проблема. Ни в теории (концептуально, это самое элегантное решение), ни на практике: этот код не будет переполнять стек . Стек достаточно большой, чтобы обрабатывать даже глубоко вложенные файловые иерархии. Задолго до того, как место в стеке станет проблемой, начинает действовать ограничение длины пути к папке.
Обратите внимание, что злонамеренный пользователь может нарушить это предположение, используя глубоко вложенные каталоги по одной букве в каждой. Я не пробовал это. Но просто чтобы проиллюстрировать это: для того, чтобы код переполнялся на типичном компьютере, каталоги должны быть вложены несколько тысяч раз. Это просто нереальный сценарий.
источник
Скопировано из MSDN :
источник
Попробуй это:
Ваши аргументы xcopy могут отличаться, но вы поняли идею.
источник
Или, если вы хотите пойти трудным путем, добавьте ссылку на ваш проект для Microsoft.VisualBasic, а затем используйте следующее:
Тем не менее, использование одной из рекурсивных функций является лучшим способом, так как он не должен загружать VB DLL.
источник
System.IO.Directory
, но это лучше, чем переписать это!Этот сайт всегда очень помог мне, и теперь моя очередь помогать другим с тем, что я знаю.
Я надеюсь, что мой код ниже будет полезен для кого-то.
источник
Path.Combine()
. Никогда не используйте конкатенацию строк для объединения путей к файлам.source_dir.Length + 1
, а неsource_dir.Length
.Рекурсивно копируйте папку без рекурсии, чтобы избежать переполнения стека.
источник
Вот вспомогательный класс, который я использовал для таких задач ввода-вывода.
источник
Возможно, он не учитывает производительность, но я использую его для папок размером 30 МБ, и он работает безупречно. Кроме того, мне не понравился весь объем кода и рекурсии, необходимых для такой простой задачи.
Примечание. ZipFile доступен в .NET 4.5+ в пространстве имен System.IO.Compression.
источник
Незначительное улучшение в ответе d4nt, поскольку вы, вероятно, хотите проверять наличие ошибок и не должны менять пути xcopy, если вы работаете на сервере и компьютере разработчика:
источник
Это мой код, надеюсь, это поможет
источник
SearchOption
флаг в поисках папок и файлов, он делает это в 4 строки кода. Также проверьте.HasFlag
расширение сейчас на enums.Если вам нравится популярный ответ Конрада, но вы хотите, чтобы
source
сама папка находилась в папкеtarget
, а не помещала в нее дочерниеtarget
элементы, вот код для этого. Возвращает вновь созданноеDirectoryInfo
, что удобно:источник
Вы всегда можете использовать это , взято с веб-сайта Microsoft.
источник
file.CopyTo(temppath, false);
написано «скопируйте этот файл в это место, только если он не существует», что в большинстве случаев не то, что мы хотим. Но я могу понять, почему это по умолчанию. Возможно, добавьте флаг в метод для перезаписи файлов.Замена Proof версии tboswell (которая устойчива к повторяющемуся шаблону в filepath)
источник
Path.Combine()
. Никогда не используйте конкатенацию строк для объединения путей к файлам.Мое решение - это, по сути, модификация ответа @ Termininja, однако я немного его улучшил, и он оказался более чем в 5 раз быстрее принятого ответа.
РЕДАКТИРОВАТЬ: Изменение @Ahmed Sabry для полностью параллельного foreach действительно дает лучший результат, однако код использует рекурсивную функцию и в некоторых ситуациях не идеален.
источник
Извините за предыдущий код, он все еще имел ошибки :( (стал жертвой самой быстрой проблемы с оружием). Здесь он протестирован и работает. Ключ - SearchOption.AllDirectories, который устраняет необходимость явной рекурсии.
источник
Вот метод расширения для DirectoryInfo в виде FileInfo.CopyTo (обратите внимание на
overwrite
параметр):источник
Используйте этот класс.
источник
.ToList().ForEach(
(что немного больше работы, памяти и немного медленнее, чем просто перечисление каталогов напрямую) и в качестве метода расширения. Выбранный ответ используетSearchOption.AllDirectories
и избегает рекурсии, поэтому я бы рекомендовал перейти на эту модель. Кроме того, вам обычно не нужно имя типа в методах расширения - я бы переименовал его, чтобыCopyTo()
оно сталоsourceDir.CopyTo(destination);
Один вариант с одним циклом для копирования всех папок и файлов:
источник
Regex
, вы, вероятно, также должны бытьRegex.Escape(path)
частью вашей композиции выражений (особенно учитывая разделитель пути Windows). Вы также можете получить выгоду от создания (и, возможно, компиляции)new Regex()
объекта вне цикла, вместо того, чтобы полагаться на статический метод.Лучше любого кода (метод расширения до DirectoryInfo с рекурсией)
источник
Скопируйте и замените все файлы папки
источник
try
catch
throw
бессмысленно.Приведенный ниже код является предложением Microsoft, как копировать каталоги, и используется совместно дорогим @iato, но он просто копирует подкаталоги и файлы исходной папки рекурсивно и не копирует исходную папку самостоятельно (например, щелчок правой кнопкой мыши -> копия ).
но ниже этого ответа есть хитрый путь :
если вы хотите скопировать содержимое из исходной папки и вложенные папки рекурсивно , вы можете просто использовать его как это:
но если вы хотите скопировать исходный каталог сам (похоже, что вы щелкнули правой кнопкой мыши на исходной папке и нажали кнопку «копировать», а затем в целевой папке, которую вы нажали вставить), вы должны использовать это так:
источник