Как скопировать папку в программу

в смысле «по-серьезнее»? копирование дерева папок это классический рекурсивный алгоритм, куда серьезнее то? разве что в вашем алгоритме не хватает защиты от исключений при работе с объектами ФС, а они будут гарантированно, если запустить программу вне подготовленной тестовой среды

15 апр 2017 в 20:26

Можете заменить классы Directory и File на DirectiryInfo и FileInfo, можно будет в одном цикле все написать, но с внутренним условием на проверку типа, или вообще в LINQ запрос завернуть в одну строчку, Только делать такого не нужно, работа с ФС требует аккуратности и внимания к исключениям. Что делать если во время копирования папки вам поменяли права на папку? и таких вопросов масса

15 апр 2017 в 20:35

ну хорошо, вот вам вольные рассуждения про файловые транзакции ru.stackoverflow.com/a/502739/198316, там вроде учтено все, включая электрика с рубильником, но ограниченное применение.

15 апр 2017 в 20:44

2 ответа 2

Сортировка: Сброс на вариант по умолчанию

скопировал папку

Времена однозадачных одно-пользовательских ОС ушли, во всяком случае на PC. Там можно было позволить себе не проверять права на файлы и не бояться. что после проверки на наличие, файла (вдруг!) не окажется при чтении. Но и там были проблемы, которые нужно было решать, например ошибки чтения на аппаратном уровне.

Файловая система штука нестабильная. Может произойти что угодно, от отключения электричества, до изменения прав вредным админом прямо во время работы вашей программы. И это нужно учитывать.

Копирование дерева папок, как базовый алгоритм не представляет сложностей, классический рекурсивный обход в глубину или ширину, на усмотрение автора. В самом вопросе и соседнем ответе их приведено несколько. Но в многопользовательской многозадачной среде придется учитывать особенности этой среды на каждом этапе алгоритма.

1. Обязательная обработка исключений.

Файловые операции могут генерировать (и генерируют) массу различных исключений (исключения File.Open ). По хорошему, каждый тип исключений нужно обрабатывать в отдельном блоке catch , почему см. ниже.

2. Копирование папки операция комплексная и долгая

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

  • на n-ном шаге операции произошло исключение: игнорировать, прервать операцию, спросить у пользователя?
  • как было сказано выше, исключения бывают разные, соответственно как будем реагировать на конкретные типы исключений?
  • что делать с уже обработанными объектами прерванной операции: удалить, оставить как есть?
  • если удалить, то как быть с замещенными файлами? Да да, должен быть бекап или теневая копия, или CVS, или что там еще можно придумать. а если их нет?
Читайте также:
Не удаляется Опера через программы и компоненты

И это я еще не упомянул возможное отключение носителя нерадивым пользователем во время копирования, битые кластеры, электрика с рубильником, соседа сварщика, погоду на Венере и еще много чего, что так или иначе может спровоцировать исключение.

КАК СКОПИРОВАТЬ ФАЙЛ ИЗ ПАПКИ в ПАПКУ

3. Серебряной пули нет

На все перечисленные и не перечисленные вопросы придется отвечать при любых операциях с файлами, в некоторых случаях ответы простые, в некоторых нет. Универсального решения тут нет. Где-то нужна надежность, где-то целостность данных, где-то скорость, а где-то отсутствие надоедливых вопросов пользователю. Цели разные, решения тоже.

Общая рекомендация может быть следующей:

  • не бойтесь исключений при работе с файловой системой, они есть и ими нужно правильно пользоваться. Для маньяков жадных до скорости и производительности — операции с объектами файловой системы на любом из современных носителей, включая RAM-диски, выполняются медленнее генерации и обработки исключений. Не экономьте на спичках.
  • забудьте про File.Exists , он не помощник в современном окружении, если конечно вашей целью является что-то кроме самой проверки на существование файла/папки.
  • оборачивайте в try catch finaly все операции с объектами файловой системы.
  • предусмотрите корректное завершение операции, прерванной исключением, если это возможно.
  • если логика программы позволяет, то оповещайте пользователя о проблемах сразу, не обязательно навязчиво, можно просто выводом в консоль или лог, если от пользователя не требуется решение, или более настойчиво, если без его активного вмешательства не обойтись.
  • если операция может повредить данные (перезапись, удаление и т.д.) переспросите пользователя в его уверенности. Да пользователи будут материться (я тоже, да да =)), но у вас и у пользователя будет хотя бы небольшая уверенность в том, что это действие выполнил именно он, а не его кот или 3-х летний ребенок.
Читайте также:
Программа fortinet была установлена неправильно Chrome

Источник: ru.stackoverflow.com

Практическое руководство. Копирование каталогов

В этой статье демонстрируется использование классов ввода-вывода для синхронного копирования содержимого каталога в другое место.

Пример асинхронного копирования файлов см. в разделе Асинхронный файловый ввод-вывод.

В этом примере копируются подкаталоги, recursive задавая CopyDirectory для параметра метода значение true . Метод CopyDirectory выполняет рекурсивное копирование подкаталогов путем вызова самого себя для каждого последующего подкаталога, пока не будет скопировано все.

Пример

Imports System.IO Module Program Sub Main(args As String()) CopyDirectory(«.», «.copytest», True) End Sub Public Sub CopyDirectory(sourceDir As String, destinationDir As String, recursive As Boolean) ‘ Get information about the source directory Dim dir As New DirectoryInfo(sourceDir) ‘ Check if the source directory exists If Not dir.Exists Then Throw New DirectoryNotFoundException($»Source directory not found: «) End If ‘ Cache directories before we start copying Dim dirs As DirectoryInfo() = dir.GetDirectories() ‘ Create the destination directory Directory.CreateDirectory(destinationDir) ‘ Get the files in the source directory and copy to the destination directory For Each file As FileInfo In dir.GetFiles() Dim targetFilePath As String = Path.Combine(destinationDir, file.Name) file.CopyTo(targetFilePath) Next ‘ If recursive and copying subdirectories, recursively call this method If recursive Then For Each subDir As DirectoryInfo In dirs Dim newDestinationDir As String = Path.Combine(destinationDir, subDir.Name) CopyDirectory(subDir.FullName, newDestinationDir, True) Next End If End Sub End Module

См. также

  • FileInfo
  • DirectoryInfo
  • FileStream
  • Файловый и потоковый ввод-вывод
  • Распространенные задачи ввода-вывода
  • Асинхронный файловый ввод-вывод

Источник: learn.microsoft.com

Как правильно скопировать файлы и папки исключая некоторые из них

Автор оригинального топика предлагает решить задачу в лоб — а именно, скопировать все файлы а потом удалить не нужные. Это может быть неплохим решением, если вам, конечно, не нужно скопировать всю домашнюю папку на флешку, за исключением вашей коллекции видео.

Но главная проблема этого подхода в другом — он не соответствует идеологии unix: сложные задачи решаются комбинацией простых утилит.

Под катом подробности о методах решения этого класса задач — не рассматривайте это как готовый рецепт.

0. Декомпозиция

Решение любой комплексной задачи начинается с разбора её на составные части. Итак нам нужно скопировать некоторый набор файлов предварительно его отфильтровав.
Значит — получение списка файлов, фильтрация, копирование.

1. Получение списка файлов

Обычно мы просматриваем список файлов программой ls. Её вывод выглядит примерно так:

Читайте также:
Чтобы записать с микрофона на компьютер программа

$ ls -1 dir1 dir2 file1.bin file2.txt

Подходит ли там такой вывод? Нет, потому, что в нем недостаточно информации — нам нужно копировать файлы рекурсивно, значит для нас было-бы гораздо удобнее если первая в нашей цепочке программа выдала там имена файлов вместе с путями.

Следующая программа, которая приходит на ум — find

$ find ./ ./ ./dir1 ./dir1/file7.txt ./dir2 ./file1.bin ./file2.txt

Уже лучше но в вывод попали и директории, а они нам не нужны. Попробуем так:
$ find ./ -type ‘f’ ./dir1/file7.txt ./file1.bin ./file2.txt

Вот то, что там нужно. Список файлов.

2. Фильтрация

Этот список файлов нужно отфильтровать. Перенаправим вывод нашей предыдущей комманды в программу grep.

$ find ./ -type ‘f’ | grep 2 ./dir2 ./file2.txt

Хорошо, но в условиях задачи стоит исключать файлы, так что немного поменеяем наш конвейер

$ find ./ -type ‘f’ | grep -v 2 ./dir1/file7.txt ./file1.bin

Первые две части выполнены.

3. Копирование

Из man-страницы для команды cp мы можем узнать, что исходный файл нужно передавать программе cp в качестве аргумента, а мы пока можем только перенаправить список на стандартный ввод.
Применим утилиту xargs — она принимает стандартный ввод и вызывает указанную программу с параметрами из стандартного ввода. Итак:

$ find ./ -type ‘f’ | grep -v 2 | xargs -n 1 -I % cp —parents «%» /path/to/dest/dir/

-n 1 значит, что только одна строка из стандартного ввода подставляется в комманду, а -I % — определяет символ, который будет заменен в целевой комманде на строчку из стандартного ввода. В нашем случае это будет

cp —parents «./dir1/file7.txt» /path/to/dest/dir/ cp —parents «./file1.bin» /path/to/dest/dir/

Можно считать, что задача решена.

Вместо заключения

Я надеюсь что это описание поможет правильно подходить к решению как таких простых так и более комплексных задач.

  • Это топик способах решения задач и немного о применении конвейера, а не о копировании файлов
  • Этот способ далеко не едиственный и даже не самый короткий, а наиболее наглядный для демонстрации методологии решения.
  • В случае этой конкретной задачи будет быстрее воспользоваться find ./ -type f ! -name «*2*» -exec cp —parents -t /target/dir «<>» +
  • Лично я воспользовался-бы tar —exclude=2 -cf — ./ | ( cd /path/to/dest/ tar -xvf — )
  • Т.к. это первый мой топик, буду рад конструктивной критике

Источник: habr.com

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru