Команда cp в Linux: полное руководство по копированию файлов и папок

Подробное руководство по команде cp в Linux: синтаксис, опции, примеры копирования файлов и директорий, сохранение атрибутов, работа с ссылками и Copy-on-Write.

Введение: зачем нужна команда cp и где она применяется

Команда cp (от англ. copy) — одна из самых часто используемых утилит в Linux. Она входит в пакет GNU Coreutils, который присутствует во всех дистрибутивах по умолчанию. С её помощью можно копировать отдельные файлы, целые директории, а также сохранять или изменять их атрибуты — права доступа, временные метки, владельца.

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

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

Синтаксис команды cp и базовые правила

Общий синтаксис команды cp выглядит так:

cp [ОПЦИИ] ИСТОЧНИК... НАЗНАЧЕНИЕ

Здесь ИСТОЧНИК — один или несколько файлов или директорий, которые нужно скопировать. НАЗНАЧЕНИЕ — конечный файл или директория. Поведение зависит от того, что вы передаёте:

  • Если и источник, и назначение — пути к файлам, cp скопирует содержимое первого во второй. Если файл назначения не существует, он будет создан.
  • Если источников несколько, назначение обязательно должно быть существующей директорией. Каждый источник будет скопирован внутрь неё с сохранением исходного имени.
  • Если источник — директория, необходимо указать опцию -R (рекурсивно), иначе команда завершится ошибкой.

Для выполнения копирования у вас должно быть как минимум право на чтение источника и право на запись в директорию назначения. Если прав недостаточно, cp выведет сообщение об ошибке и не выполнит операцию.

Копирование одного или нескольких файлов

Самый простой пример — скопировать файл в текущей директории с новым именем:

cp file.txt file_backup.txt

Если нужно скопировать файл в другую директорию, укажите путь к ней:

cp file.txt /backup/

При этом файл сохранит исходное имя. Чтобы одновременно переименовать его, добавьте новое имя в путь назначения:

cp file.txt /backup/new_file.txt

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

cp file1.txt file2.txt file3.txt /backup/

Удобный способ — использовать маску по расширению:

cp *.txt /backup/

Обратите внимание: если в директории назначения уже есть файл с таким же именем, по умолчанию cp перезапишет его без предупреждения. Чтобы изменить это поведение, используйте опции -i (запрос подтверждения) или -n (пропуск существующих файлов).

Копирование директорий: рекурсивный и архивный режимы

Для копирования директорий обязательно использовать опцию -R (или -r):

cp -R Pictures Pictures_backup

Если директория Pictures_backup не существует, она будет создана, и всё содержимое Pictures окажется внутри неё. Если же Pictures_backup уже существует, то Pictures будет скопирована внутрь неё, и вы получите структуру Pictures_backup/Pictures/.... Это часто приводит к путанице, поэтому будьте внимательны.

Чтобы скопировать только содержимое директории, а не саму папку, используйте комбинацию с точкой в конце источника:

cp -a Pictures/. Pictures_backup/

В этом случае все файлы и подпапки из Pictures попадут непосредственно в Pictures_backup, без дополнительного уровня вложенности. Альтернативный способ — опция -T (no-target-directory), которая заставляет cp трактовать назначение как конечный путь, а не контейнер:

cp -rT Pictures Pictures_backup

Для полного сохранения всех атрибутов (прав доступа, владельца, временных меток, символических и жёстких ссылок) используйте опцию -a (archive). Она эквивалентна -dR --preserve=all и является стандартным выбором для создания точных резервных копий.

Управление перезаписью и создание резервных копий

По умолчанию cp перезаписывает существующие файлы без предупреждения. Чтобы запрашивать подтверждение, используйте -i (interactive):

cp -i file.txt /backup/

Если нужно никогда не перезаписывать существующие файлы, применяйте -n (no-clobber). В новых версиях GNU coreutils (9.3+) рекомендуется использовать --update=none для той же цели, но с более явным синтаксисом.

Опция -u (update) копирует файл только в том случае, если источник новее назначения или если файл назначения отсутствует. Это удобно для инкрементального резервного копирования.

Для сохранения старой версии файла перед перезаписью используйте -b (backup). По умолчанию к имени добавляется символ тильды (~). Суффикс можно изменить с помощью --suffix:

cp -b --suffix=.orig file.txt /backup/

Более гибкое управление резервными копиями даёт опция --backup=CONTROL, где CONTROL может принимать значения:

  • none или off — не создавать резервные копии;
  • numbered или t — добавлять номер (file.txt.~1~, file.txt.~2~ и т.д.);
  • existing или nil — использовать нумерацию, если уже есть пронумерованные копии, иначе простой суффикс;
  • simple или never — всегда добавлять суффикс.

Нумерованные резервные копии особенно полезны при многократном копировании одного и того же файла — каждая предыдущая версия сохраняется.

Сохранение атрибутов файлов: владелец, права, временные метки

При обычном копировании cp создаёт новый файл с текущими временными метками и правами доступа, установленными по умолчанию (обычно на основе umask). Чтобы сохранить оригинальные атрибуты, используйте опцию -p (preserve), которая эквивалентна --preserve=mode,ownership,timestamps:

cp -p file.txt /backup/

Для более тонкого контроля применяйте --preserve=ATTR_LIST, где ATTR_LIST — список атрибутов через запятую:

  • mode — права доступа (включая ACL и расширенные атрибуты);
  • ownership — владелец и группа;
  • timestamps — временные метки (время последнего доступа, изменения и создания);
  • links — жёсткие ссылки между копируемыми файлами;
  • context — контекст SELinux;
  • xattr — расширенные атрибуты (например, установленные через chattr);
  • all — все перечисленные выше.

Обратите внимание: обычный пользователь может сохранить группу только если сам входит в неё, а изменить владельца на другого пользователя может только root. Если какой-то атрибут не удаётся сохранить, cp выведет диагностическое сообщение, но файл будет скопирован.

Для полного сохранения всех атрибутов и структуры (включая символические и жёсткие ссылки) используйте опцию -a, которая объединяет рекурсивное копирование с сохранением всего.

Работа с символическими и жёсткими ссылками

По умолчанию cp разыменовывает символические ссылки: вместо самой ссылки копируется файл, на который она указывает. Если нужно скопировать именно ссылку как ссылку, используйте опцию -P (no-dereference):

cp -P link1 /backup/

Для жёстких ссылок ситуация иная. По умолчанию cp создаёт отдельную копию файла, разрывая связь с оригиналом. Чтобы сохранить жёсткую ссылку как ссылку (то есть чтобы несколько скопированных файлов указывали на одни и те же данные), используйте --preserve=links:

cp --preserve=links hlink1 /backup/

Опция -d объединяет оба поведения: она копирует символические ссылки как ссылки и сохраняет жёсткие ссылки между файлами. Это часть того, что делает -a.

Если вам нужно, наоборот, разыменовать все ссылки в дереве директорий (заменить каждую ссылку копией её цели), используйте -L (dereference). Это полезно, когда копия переносится на другую машину, где целевые файлы могут отсутствовать:

cp -RL site site_snapshot

Будьте осторожны: если ссылка указывает на большой каталог за пределами копируемого дерева, -L скопирует и его, что может привести к неожиданному расходу места.

Продвинутые возможности: Copy-on-Write, разреженные файлы и verbose

Современные файловые системы, такие как Btrfs, XFS и bcachefs, поддерживают механизм Copy-on-Write (CoW). При его использовании cp не дублирует все блоки данных сразу, а создаёт «рефлинк» (reflink), который разделяет те же блоки до момента изменения одного из файлов. Это делает копирование больших файлов практически мгновенным и экономит место.

Начиная с GNU coreutils 9.0, cp по умолчанию работает в режиме --reflink=auto: пытается создать рефлинк, а если файловая система не поддерживает — выполняет обычное копирование. Вы можете явно управлять этим поведением:

  • --reflink=always — всегда использовать CoW, при неудаче выдавать ошибку;
  • --reflink=never — принудительно выполнять полное копирование данных.

Рефлинки полезны для быстрых снимков, но помните: ошибка ввода-вывода в общем блоке может повлиять на оба файла. Для полностью независимых резервных копий на отдельном носителе используйте --reflink=never.

Разреженные файлы — это файлы, содержащие большие последовательности нулевых байт, которые файловая система хранит неявно, экономя место. Типичный пример — образы виртуальных машин (QEMU, VirtualBox). По умолчанию cp сохраняет разреженность, если источник был разреженным. Опция --sparse позволяет изменить это поведение:

  • auto — по умолчанию, копирует как есть;
  • never — записывает все нулевые байты явно, делая файл полным;
  • always — пытается сделать любой файл разреженным, если в нём достаточно нулей.

Для детального вывода процесса копирования используйте -v (verbose). Команда будет выводить каждое копируемое имя:

cp -v file.txt /backup/
'file.txt' -> '/backup/file.txt'

Это особенно полезно при копировании большого количества файлов, чтобы убедиться, что всё идёт по плану.

Типичные ошибки и как их избежать

Даже опытные пользователи иногда допускают ошибки при работе с cp. Вот наиболее частые из них:

  1. Забыли опцию -R при копировании директории. Команда cp dir /backup/ завершится ошибкой cp: omitting directory. Всегда добавляйте -r или -a для каталогов.
  1. Неожиданная вложенность при копировании в существующую директорию. Если вы выполните cp -r Pictures /backup/, а /backup/ уже существует, то внутри /backup/ появится подпапка Pictures. Чтобы скопировать только содержимое, используйте Pictures/. или опцию -T.
  1. Перезапись важных файлов. По умолчанию cp перезаписывает без предупреждения. Если вы не уверены, используйте -i или -n. Особенно аккуратно работайте с алиасами: в некоторых дистрибутивах (например, Manjaro) cp может быть алиасом на cp -i, что приводит к неожиданным запросам. Проверить алиасы можно командой type -a cp.
  1. Потеря атрибутов при резервном копировании. Если вы копируете системные файлы или данные, которые должны сохранить права доступа и временные метки, всегда используйте -a или -p. Иначе восстановление может привести к неработоспособности.
  1. Игнорирование скрытых файлов. При копировании содержимого директории с помощью маски * (например, cp source/* destination) скрытые файлы (начинающиеся с точки) не будут скопированы. Для их включения используйте source/. или shopt -s dotglob.
  1. Проблемы с правами доступа. Если вы не можете скопировать файл, проверьте, есть ли у вас право на чтение источника и запись в директорию назначения. Для копирования файлов других пользователей может потребоваться sudo.

Практические примеры для повседневной работы

Рассмотрим несколько реальных сценариев, где cp незаменим:

1. Резервное копирование конфигурационного файла перед редактированием:

cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

2. Копирование всех логов за сегодня в отдельную папку:

cp /var/log/*.log /backup/logs/

3. Создание точной копии проекта для тестирования:

cp -a /home/user/project /home/user/project_test

4. Инкрементальное копирование только изменённых файлов:

cp -u /home/user/documents/* /backup/documents/

5. Копирование с переименованием и сохранением атрибутов:

cp -p report.pdf /archive/report_2025.pdf

6. Быстрое создание рефлинка большого образа диска:

cp --reflink=always disk.img disk_snapshot.img

7. Копирование содержимого папки с игнорированием вложенности:

cp -rT /source/dir /destination/dir

Эти примеры покрывают большинство повседневных задач. Комбинируя опции, вы можете адаптировать cp под любые нужды.

Вопросы и ответы

Как скопировать файл с сохранением всех атрибутов?

Используйте опцию -p (preserve) для сохранения прав доступа, владельца и временных меток: cp -p source destination. Для полного сохранения всех атрибутов, включая расширенные, применяйте --preserve=all или опцию -a, которая также выполняет рекурсивное копирование.

В чём разница между cp -r и cp -a?

cp -r (или -R) выполняет рекурсивное копирование директории, но не сохраняет атрибуты файлов — новые файлы получают текущие временные метки и права по умолчанию. cp -a (archive) эквивалентна -dR --preserve=all: она копирует рекурсивно, сохраняет символические и жёсткие ссылки, а также все атрибуты (права, владельца, временные метки, SELinux-контекст, расширенные атрибуты). Для точных резервных копий всегда используйте -a.

Как предотвратить перезапись существующих файлов при копировании?

Используйте опцию -n (no-clobber): cp -n source destination. В новых версиях GNU coreutils (9.3+) также доступна опция --update=none, которая делает то же самое, но с более явным синтаксисом. Если вы хотите, чтобы команда спрашивала подтверждение перед каждой перезаписью, используйте -i.

Как скопировать только содержимое папки, без самой папки?

Есть два основных способа. Первый: добавьте точку в конце пути источника — cp -a source/. destination/. Второй: используйте опцию -T (no-target-directory) — cp -rT source destination. В обоих случаях все файлы и подпапки из source будут скопированы непосредственно в destination, без создания дополнительного уровня вложенности.

Что такое Copy-on-Write и как его использовать с cp?

Copy-on-Write (CoW) — механизм, при котором копирование больших файлов выполняется практически мгновенно, без дублирования данных на диске, пока один из файлов не будет изменён. Поддерживается файловыми системами Btrfs, XFS и bcachefs. В cp управление CoW осуществляется через опцию --reflink: --reflink=auto (по умолчанию, пытается использовать CoW), --reflink=always (требует CoW, иначе ошибка), --reflink=never (всегда полное копирование).

Почему cp спрашивает подтверждение, хотя я не указывал опцию -i?

Скорее всего, в вашем дистрибутиве cp определён как алиас (псевдоним) с опцией -i. Проверьте это командой type -a cp. Если вывод содержит cp is aliased to 'cp -i', то каждый вызов cp автоматически добавляет флаг -i. Чтобы временно отключить алиас, используйте command cp или \cp. Для постоянного изменения отредактируйте файл конфигурации вашей оболочки (например, ~/.bashrc).

Как скопировать символическую ссылку как ссылку, а не файл, на который она указывает?

Используйте опцию -P (no-dereference): cp -P link destination. В этом случае будет скопирована сама символическая ссылка, а не её цель. Если вы хотите сохранить и символические, и жёсткие ссылки, используйте -d или -a.