Что значит рекурсивное копирование
Команда cp: правильное копирование папок с файлами в *nix
В этой статье будут раскрыты некоторые неочевидные вещи связанные с использованием wildcards при копировании, неоднозначное поведение команды cp при копировании, а также способы позволяющие корректно копировать огромное количество файлов без пропусков и вылетов.
Допустим нам нужно скопировать всё из папки /source в папку /target.
Первое, что приходит на ум это:
Сразу исправим эту команду на:
После копирования мы обнаружим, что скопировались не все файлы — были проигнорированы файлы начинающиеся с точки типа:
.profile
.local
.mc
и тому подобные.
Почему же так произошло?
Потому что wildcards обрабатывает shell ( bash в типовом случае). По умолчанию bash проигнорирует все файлы начинающиеся с точек, так как трактует их как скрытые. Чтобы избежать такого поведения нам придётся изменить поведение bash с помощью команды:
Чтобы это изменение поведения сохранилось после перезагрузки, можно сделать файл wildcard.sh c этой командой в папке /etc/profile.d (возможно в вашем дистрибутиве иная папка).
Однако, если в папке тысячи файлов и больше, то от подхода с использованием wildcards стоит отказаться вовсе. Дело в том, что bash разворачивает wildcards в очень длинную командную строку наподобие:
На длину командной строки есть ограничение, которое мы можем узнать используя команду:
Получим максимальную длину командной строки в байтах:
Получим что-то типа:
Итак, давайте будем обходиться вовсе без wildcards.
Давайте просто напишем
Однако, если папка target существует, то файлы будут скопированы в папку /target/source.
Не всегда мы можем удалить заранее папку /target, так как в ней могут быть нужные нам файлы и наша цель, допустим, дополнить файлы в /target файлами из /source.
Если бы папки источника и приёмника назывались одинаково, например, мы копировали бы из /source в /home/source, то можно было бы использовать команду:
И после копирования файлы в /home/source оказались бы дополненными файлами из /source.
Такая вот логическая задачка: мы можем дополнить файлы в директории-приёмнике, если папки называются одинаково, но если они отличаются, то папка-исходник будет помещена внутрь приёмника. Как скопировать файлы из /source в /target с помощью cp без wildcards?
Чтобы обойти это вредное ограничение мы используем неочевидное решение:
Те кто хорошо знаком с DOS и Linux уже всё поняли: внутри каждой папки есть 2 невидимые папки «.» и «..», являющиеся псевдопапками-ссылками на текущую и вышестоящие директории.
Поведение этой команды однозначно. Всё отработает без ошибок вне зависимости от того миллион у вас файлов или их нет вовсе.
Выводы
Если нужно скопировать все файлы из одной папки в другую, не используем wildcards, вместо них лучше использовать cp в сочетании с точкой в конце папки-источника. Это скопирует все файлы, включая скрытые и не завалится при миллионах файлов или полном отсутствии файлов.
Послесловие
vmspike предложил аналогичный по результату вариант команды:
ВНИМАНИЕ: регистр буквы T имеет значение. Если перепутать, то получите полную белиберду: направление копирования поменяется.
Благодарности:
Когда бы я не хотел такого поведения при копировании каталога?
Разве рекурсивная копия каталога не является поведением по умолчанию; поведение мы хотим почти все время?
Такое ощущение, что это лишний флаг.
Итак, с точки зрения командной строки, делая это:
Теперь о том, почему это может показаться излишним или избыточным, это действительно сводится к историческим методам работы с файловыми системами. А также создание системы, которая защищена от всех типов ошибок, связанных с пользователем; случайный, а также преднамеренный.
То есть, допустим, у вас есть
Если это кажется излишним, то не нужно смотреть дальше, чем современная система графического интерфейса, которую можно поместить над файловыми системами Linux. Графический интерфейс пользователя решает основные пользовательские проблемы, такие как эта, позволяя легко перетаскивать файлы и каталоги.
Точно так же именно поэтому файловые системы Linux / Unix не имеют 777 разрешений и sudo прав, установленных по умолчанию, и то, как настоящие системные администраторы вздрагивают, когда пользователь устанавливает 777 разрешения или предоставляет всем sudo права. Это основные вещи, которые нужно сделать, чтобы система была стабильной и как можно более «пользовательской»; любой, кто поспешит заморозить эти соглашения, скорее всего, нанесет ущерб их системе, даже не подозревая об этом.
ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ: Другой ответ здесь, на сайте Unix Stack Exchange, дает хорошее объяснение того, почему нерекурсивная копия каталога является проблематичной; Акцент мой.
Это правда, что такое поведение мы хотим почти все время. Однако это не обязательно означает, что рекурсивное копирование должно быть поведением по умолчанию.
Копируем файлы и папки в терминале Linux
В данной статье мы разберемся как копировать в терминале Linux папки и файлы. Эти знания вам могут пригодится, если вдруг у вас не будет графического окружения Linux. Да и знания терминала вам поможет в освоении Linux систем, хотя на данный момент можно обойтись в некоторых дистрибутивах вообще без терминала. Но, терминал, это основа Linux, и без него вам может быть тяжко в решении каких либо ситуаций. На сайте уже имеются некоторые статьи на тему освоения терминала в Linux, так что при желании вы можете их найти и ознакомится с ними. Ну а мы вернемся к теме копирования файлов и папок в терминале Linux. При копировании, да и вообще система Linux чувствительна к регистру, так что вводя команды будьте внимательны.
Копирование в терминале Linux
Для копирования используется команда “cp”, у нее так же имеются некоторые опции, о которых вы узнаете чуть позже. Для того что бы скопировать какие то файлы или папки, необходимо ввести команду “cp”, далее, при необходимости указать путь до директории где находится папка или файл который вы ходите скопировать. После чего указываем путь до директории куда хотим скопировать. Так же возможно, вне домашнего каталога вам придется работать от root пользователя при копировании информации. И так, давайте приступим, например, мне необходимо скопировать файл под названием “test” в директорию “Документы”. Для этого ввожу команду “cp” далее название файла и путь куда хочу скопировать данный файл. При это не забываем про регистр, как мы помним, Linux чувствителен к нему:
Теперь усложним немного и скопируем файл который находится в директории “/tmp”. Как вы помните, при копировании вне домашнего каталога вам нужны будут права root пользователя. А иначе у вас не чего не получится:
Что бы получить права root пользователя на копирования из директории “/tmp”, как вы могли уже догадаться, необходимо перед командой “cp” ввести слово “sudo”:
Предположим, нам необходимо скопировать данный файл по другим именем, для этого снова вводим команду “cp”, далее путь к файлу и путь куда хотим скопировать данный файл. Но, в конце пути куда хотим скопировать, необходимо ввести новое название того файла, который копируем. Например, я хочу скопировать файл “test-file” из директории “/tmp” и переименовать его в “test-cp”, что бы вам было более наглядно, выделю жирным старое название файла, а затем новое:
Рекурсивное копирование
При необходимости точно так же как и файлы при копировании, название папки можно изменить, например, назовем папку “test-cp” просто “test”:
При копировании файла в нужную вам директорию, предыдущий файл с таким же именем просто перезапишется. То есть, если вы копируете файл “test-file” из директории “/tmp”, в директорию “Документы”, он заменит в директории уже имеющийся файл “test-file”. Что бы избежать перезаписывания файлов необходимо вести опцию “-i”, тогда при копировании вам будет предложен выбор, перезаписать файл или нет. Вы можете выбрать да или нет, указав это буквами “y- да, перезаписать” или “n- нет, не перезаписывать”:
Заключение
Я уже не раз писал, что не стоит боятся терминала Linux, в нем нет ни чего сложно, а порой, бывает и так, что работа в терминале облегчает пользователю жизнь. Так же, если вы пользователь Debian и у вас по каким то причинам нет sudo, вы можете перейти к статье о настройке Debian и добавить вашего пользователя в группу sudo. Вы всегда можете набрать команду “cp –help” для получения справки по данной команде.
А на этом сегодня все. Надеюсь данная статья будет вам полезна.
Журнал Cyber-X
Копирование файлов и директорий: команда cp в Linux и MacOS
Перевод статьи «Copy a Directory in Linux – How to cp a Folder in the Command Line in Linux and Unix (MacOS)».
Команда cp относительно простая, но ее поведение может изменяться в зависимости от передаваемых опций и того, что именно (файлы или директории) и куда копируется.
Для просмотра документации или руководства по использованию команды cp выполните в терминале команду man cp :
В своей базовой форме эта команда принимает в качестве инпута источник, который вы хотите скопировать, и «пункт назначения» — то, куда именно вы хотите его скопировать. Источником может быть файл, несколько файлов или вообще директория.
Как создать копию файла в текущей директории
Чтобы создать копию файла в той же директории, нужно передать команде cp имя исходного файла и имя, которое нужно дать файлу-копии.
Допустим, у вас есть файл a.txt и вы хотите создать его копию под именем b.txt в той же директории:
Для справки: команда ls выводит список файлов в текущей директории.
По умолчанию команда cp использует в качестве пути к файлам вашу текущую директорию.
Как скопировать файл в другую директорию
Чтобы скопировать файл в директорию, отличную от вашей текущей, нужно просто указать путь к ней:
После выполнения команды cp ранее пустая directory-1 содержит файл a.txt.
По умолчанию копируемый файл сохраняет свое имя, но вы можете указать любое другое:
Как скопировать несколько файлов в другую директорию
Чтобы одновременно скопировать несколько файлов, вы можете передать команде несколько источников, а в конце указать пункт назначения:
В этом примере оба файла (first.txt и second.txt) были скопированы в директорию directory-1.
Примечание: при передаче нескольких источников последний аргумент обязательно должен быть директорией.
Как скопировать одну директорию в другую
Если вы попытаетесь передать команде cp в качестве источника имя директории, вы получите ошибку:
В следующем примере у нас есть две директории (directory-1 и directory-2), расположенные в нашей текущей директории. В directory-1 есть файл a.txt. Мы рекурсивно копируем directory-1 в directory-2. После этого в нашей текущей директории по-прежнему есть directory-1 и directory-2, при этом в directory-2 есть копия directory-1, содержащая файл a.txt.
Копирование директории целиком и копирование всего содержимого из директории
Примечание редакции Techrocks. Когда мы попробовали применить эту инструкцию в терминале Linux, у нас ничего не вышло. В одной статье мы нашли, что описанный функционал работает в MacOS, но не в Linux. Поэтому здесь мы сначала приведем перевод инструкций автора, а затем от себя дополним их.
При копировании директории есть интересный нюанс. Если директория, которую вы указываете как пункт назначения, уже существует, вы можете скопировать в нее либо все содержимое директории-источника, либо всю директорию-источник целиком. Выбор регулируется добавлением конечного слэша / к имени директории-источника.
Для пользователей Linux: после слэша нужно добавить точку. Если хотите почитать более подробно, вот хорошая статья на Хабре.
Как предотвратить перезапись файлов при копировании
По умолчанию команда cp перезаписывает существующие файлы. Для примера создадим в текущей директории файл a.txt с текстом A, а в директории directory-1 — файл a.txt с текстом B. При копировании файла a.txt из текущей директории в directory-1 файл a.txt перезаписывается (в его содержимом было B, стало A).
Примечание: команда cat среди прочего служит для вывода содержимого файлов на экран.
Есть два способа предотвратить перезапись файлов.
Флаг —interactive
Флаг —no-clobber
Другие опции
Что значит рекурсивное копирование
Копирование файлов (POSIX)
cp [-f|-i] [-Rrp] [Расширения QNX Neutrino]
cp [-f|-i] [-Rrp] [Расширения QNX Neutrino]
QNX Neutrino, Linux, Microsoft Windows
( Расширение QNX Neutrino.) Сохранить время доступа к исходному файлу.
( Расширение QNX Neutrino.) Использовать очень небольшой буфер для копирования (2 Кб)
утилита cp выполняет эквивалент следующего:
cp file /home/eric/source/file
Выполнить в интерактивном режиме; всегда выдавать приглашение на подтверждение наличия целевого пути, вне зависимости от полномочий на изменение целевого файла. Опция -i позволяет избежать случайного затирания информации в файлах при копировании. При отсутствии полномочий на запись в выходной файл и положительном ответе на запрос сначала удаляется ссылка на целевой файл. В противном случае выходной файл перезаписывается и усекается.
( Расширение QNX Neutrino.) Создавать рекурсивные копии в режиме UNIX (по умолчанию) или в прежнем режиме QNX.
Ранее в QNX выполнялось копирование содержимого каталогов, перечисленных в командной строке, в результирующий каталог. В UNIX в результирующий каталог копируется непосредственно сам каталог (как при выборе mv ). В любом случае, если копируется только один каталог, а в качестве целевого указан несуществующий каталог, с помощью утилиты cp создается целевой каталог, в который копируется содержимое исходного каталога.
Примечание. Режим по умолчанию в QNX Neutrino отличается от аналогичного режима в QNX 4.
Для получения дополнительной информации см. раздел «Рекурсивное копирование» далее.
После добавления опции -N пример выглядит следующим образом:
( Расширение QNX Neutrino.) Копировать только при отсутствии целевого файла.
( Расширение QNX Neutrino.) Копировать только при наличии целевого файла.
Путь для копирования единственного файла.
Путь к существующему каталогу, который должен содержать выходной файл (выходные файлы).
Для утилиты cp существуют две формы синтаксиса:
cp [ -f | -i ] [ -Rrp ] [ Расширения QNX Neutrino ] исходный_файл конечный_файл
cp [ -f | -i ] [ -Rrp ] [ Расширения QNX Neutrino ] исходный_файл. результ_каталог
cp dir/dir/myfile /existingdir
Вторая форма применяется, когда целевой файл является существующим каталогом или при определении нескольких исходных файлов.
Поведение утилиты cp в случае, если целевой файл уже существует, зависит от используемых опций. Если опция -f или -i не выбрана, то утилита cp выдает приглашение только при отсутствии полномочий на изменение существующего целевого файла. При этом сначала выводится запрос о необходимости удаления ссылки на файл. Если ответ на запрос отрицательный, то утилита cp продолжает обработку всех остальных файлов. Запрос выводится только в том случае, если стандартным потоком ввода stdin является терминал ввода вывода. В противном случае утилита cp выводит в стандартный поток ошибок stderr диагностическое сообщение и пропускает файл.
При копировании файлов на съемный носитель, например гибкий или съемный диск, и переполнении этого носителя утилита cp закрывает и удаляет не полностью скопированный целевой файл, выводит соответствующее сообщение, а затем завершается.
При рекурсивном копировании каталога целевым местоположением должен быть каталог. При копировании нескольких элементов соответствующий каталог должен уже существовать. При копировании одного каталога утилита cp создает целевой каталог (все промежуточные каталоги должны уже существовать, если не выбрана опция -c ).
Для cp доступны два режима рекурсивного копирования:
При выборе режима по умолчанию ( -Munix ) утилита cp дублирует исходный каталог в целевом (если не выполняется копирование только одного каталога и целевой каталог уже существует – в этом случае режимы — Munix и -Mqnx ничем не отличаются).
Примечание. Режим по умолчанию в QNX Neutrino отличается от аналогичного режима в QNX 4
cp файл1 файл2 файл3 /home/eric
Та же операция в режиме рекурсивного копирования QNX:
Рекурсивное копирование содержимого текущего каталога в каталог /mydir/ в режиме -Mqnx или -Munix :
Та же операция в режиме -Munix :
Рекурсивное копирование каталога /home/eric в каталог /backups/eric :
Та же операция в режиме рекурсивного копирования QNX:
Если опция -r не выбрана и указан только один исходный файл, этот исходный файл может быть любого типа.
В случае использования опции -R файлы FIFO дублируются в структуру целевого каталога, но содержимое исходных FIFO не копируется. При обнаружении утилитой cp в исходных файлах блок-ориентированных или байт-ориентированных специальных файлов возникает ошибка, поскольку утилита cp не может создавать их в целевом местоположении.
Каждый новый выходной файл относится к одному из следующих типов файлов:
каталог, содержащий копии файлов и подкаталогов (если они существуют), обнаруженных во входном каталоге;
стандартный файл с таким же содержимым, как и в соответствующем входном файле.
FIFO, созданный в результате выбора опции -R и определения FIFO в качестве соответствующего входного файла. Данные исходного FIFO не копируются в новый FIFO (т.е. новый FIFO остается пустым).
Если в существующем целевом каталоге определены другие типы файлов, утилита cp открывает этот каталог для записи и предпринимает попытку копирования в него содержимого соответствующего входного файла.
От этой переменной зависит, копируется ли время изменения файла. При ее определении опции расширения QNX Neutrino деактивируются.
Определение переменной среды POSIX_STRICT влияет на опции -p и — t следующим образом:
Если целевое местоположение не существует, дублируется только режим.
Если целевое местоположение не существует, дублируется только режим.
Дублируются время и режим.
Если целевое местоположение не существует, дублируется только режим.
Все входные файлы скопированы успешно.
Если утилита cp выполняет копирование нескольких файлов или рекурсивное копирование, но опция — R не выбрана, то cp не копирует файл FIFO и байт-ориентированные специальные файлы.
Если опция -R указана и предпринятая утилитой cp попытка копирования определенного файла в указанной иерархии файлов завершается неуспешно, то выполняется обработка остальных файлов в этой иерархии.