323

Как скопировать с помощью cp, чтобы включить скрытые файлы и скрытые каталоги и их содержимое?


Как сделать так, чтобы cp -r копировал абсолютно все файлы и каталоги в каталоге?

Требования:

  • Включите скрытые файлы и скрытые каталоги.
  • Будьте одной командой с флагом, чтобы включить выше.
  • Не нужно полагаться на сопоставление с образцом вообще.

Мой некрасивый, но работающий хак это:

cp -r /etc/skel/* /home/user
cp -r /etc/skel/.[^.]* /home/user

Как я могу сделать все это в одной команде без сопоставления с образцом? Какой флаг мне нужно использовать?

Пожалуйста, Eleven81, рассмотрите возможность изменения принятого ответа на ответ, заданный @bruno pereira, потому что он избегает создания новой папки. Если нет, то пусть этот комментарий будет предупреждением для новых читателей, чтобы проверить также другой (наиболее проголосовавший) ответ. Tx. (12 июля 16 августа в 20:27)

Ответов: 13

232

Не указывайте файлы:

cp -r /etc/skel /home/user

(Обратите внимание, что /home/user не должен уже существовать, иначе он создаст /home/user/skel .)

Можно ли использовать нечто подобное, если /home/user/skel существует ? (24 августа '11 в 2:10)

@ bradley.ayers Я думаю, что можно скопировать во временный подкаталог, а затем переместить их на верхний уровень (так как перемещение на одном диске происходит быстро). Менее чем идеал, но короче, чем другие решения для меня. (16 марта '13 в 9:58)

@ bradley.ayers Ответ Бруно, приведенный ниже, отвечает на ваш вопрос (20 августа '13 в 15:38)

Это решение не сработало для меня. Он не копировал скрытые файлы. Я использую CentOS релиз 6.5. Решение @ Бруно сработало. (29 января '16 в 13:02)

В Ubuntu/Debian это помещает каталог 'skel' в целевой каталог, а не рекурсивные файлы внутри skel. Используйте -T (без цели), как показано ниже для правильного использования. ( -rT для рекурсии) (23 июня '17 в 15:45)

Это не копирует скрытые (точечные) файлы, такие как «.profile» или «.bashrc» (15 августа '17 в 4:49)

Если /home/user существует, то это скопирует содержимое /etc/skel без указания /home/user/skel : < code> find/etc/skel -type f -exec cp {}/home/user \; (14 сентября '17 в 10:39)

Остерегайтесь , что это не сохраняет атрибуты файла по умолчанию. Поэтому убедитесь, что вы добавили свою комбинацию меток времени/xattr/etc. через -p/- флаг сохранения! (сравните справочную страницу) (7 января '18 в 19:34)
415

Допустим, вы создали новую папку (или собираетесь ее создать) и хотите скопировать в нее файлы после ее создания.

mkdir /home/<new_user>
cp -r /etc/skel/. /home/<new_user>

Это позволит рекурсивно скопировать все файлы/папки из /etc/skel в уже существующую папку, созданную в первой строке.

Если я не ошибаюсь, это не копирует скрытые/точечные файлы. (16 марта '13 в 9:56)

Хорошо работает для меня. Обратите внимание, что "." имеет решающее значение для его работы. (20 августа '13 в 15:39)

Это работает, но почему? Не могу найти ссылку на это в руководстве. (14 января '14 в 13:37)

Это лучший ответ на то, что мне было нужно и, вероятно, многим другим. (7 апреля '14 в 22:04)

Я думаю, что это работает, потому что обычно это создает новую папку с именем последней папки в первом аргументе. Однако, так как это имя . , для такого поведения потребуется создать уже существующий каталог, поэтому он просто пропускает этот шаг. (11 июня '14 в 20:07)

Считается, что редактирование, но будет комментировать, чтобы дать больше возможностей для обзора. Я думаю, что должна быть третья командная строка с надписью chown -R & lt; new_user & gt;: & lt; new_user & gt;/home/& lt; new_user & gt; для передачи права собственности на файлы новому пользователю. (11 февраля '15 в 20:26)

Ну, я не согласен, текущий ответ является правильным для вопроса. Вам также необходимо отредактировать заголовок вопроса (и сам вопрос), чтобы сопоставить предлагаемое изменение с этим ответом. (11 февраля 15 в 20:55)

Ну, это никогда не плохо, если ответ лучше, чем вопрос. Может быть в отдельной заметке. Если вы этого не сделаете, вы получите нерабочий, что может удивить, потому что системные инструменты, которые копируют скелет, автоматически проверяют правильность владения. Я бы даже сказал, что это решение вопроса, но он создает новую проблему на пути, который он не решает. (12 февраля '15 в 12:13)

Обратите внимание, что ответы предназначены не только для ОП, но и для всех, кто находит страницу через веб-поиск. (12 февраля '15 в 12:14)

Это работает потому, что это эквивалентно cp -r/etc/skel/home/& lt; new_user & gt; . Точка . - это эквивалентное оболочке имя для « This directory », так же как двойная точка .. означает « Перейти вверх». один каталог "относительно заданного пути. Это относительный указатель пути. Попробуйте это: ls -d/etc/skel /. Вы должны увидеть, что bash eval это для: /etc/skel /. If вы должны попробовать ls -l/home/& lt; myuser & gt; /. , вы увидите файлы в /home/& lt; myuser & gt; (20 марта '15 в 18:00)

@BrunoPereira: Спасибо! Ваше решение сработало для меня, но мне любопытно узнать, почему используется "." (точка) копирует скрытый файл. (29 января '16 в 13:04)

Hy @Technext, объяснение от TrinitronX, кажется, на месте: не мог объяснить это лучше сам. (1 февраля '16 в 13:01)

Хммм ... я прочитал его комментарий, но был смущен, почему * не работает. Кажется * соответствует всем, кроме точечных (.) Файлов. (1 февраля '16 в 13:26)

@Technext Глобализация по умолчанию в bash не включает имена файлов, начинающиеся с . , чтобы изменить это, вам нужно использовать команду shopt -s dotglob перед тем, чтобы иметь возможность включать эти файлы. Таким образом, с помощью * по умолчанию вы запрашиваете рекурсивное копирование всех файлов из этого каталога, которые можно развернуть с помощью * (который по умолчанию не содержит скрытых файлов). На другом конце с . вы используете cp для рекурсивного копирования всего из «этого каталога». (1 февраля '16 в 20:39)

@BrunoPereira: Большое спасибо за объяснение! :) Теперь все понятно. :) (2 февраля '16 в 13:08)

Это должен быть принятый ответ (15 августа '17 в 4:48)
63

bash самого bash есть хорошее решение, у него есть shell option, вы можете cp, mv и так далее.

shopt -s dotglob # for considering dot files (turn on dot files)

а также

shopt -u dotglob # for don't considering dot files (turn off dot files)

Выше решение является стандартом bash

НОТА:

shopt # without argument show status of all shell options
-u # abbrivation of unset 
-s # abbrivation of set

Это полезно, когда вы хотите скопировать только содержимое, не создавая новый каталог в месте назначения. Особенно, когда пункт назначения является точкой монтирования. (11 ноября '13 в 12:27)

Это действительно лучший ответ, и он дает суть вопроса .. (23 мая '14 в 16:51)

Это setopt для zsh, если кому-то еще интересно. (29 декабря '14 в 23:18)
56

Правильный способ сделать это - использовать опцию -T (--no-target-directory) и рекурсивно копировать папки (без конечных слешей, звездочек и т.д.), То есть:

cp -rT /etc/skel /home/user

Это скопирует содержимое /etc/skel в /home/user (включая скрытые файлы), создав папку /home/user если она не существует; однако опция -T предотвращает копирование содержимого /etc/skel в новую папку /home/user/skel если папка /home/user существует.

Правильный ответ. +1 (23 июня '17 в 15:47)

это был действительно правильный ответ (27 февраля '18 в 16:12)

это ЛУЧШИЙ ответ из группы; Это единственный, который решает проблему, не усложняя ее (12 сентября '18 в 18:25)
23

Используйте rsync:

rsync -rtv source_folder/ destination_folder/

Лучший вариант для меня, хотя я использую --progress, чтобы получить больше отзывов обо всем процессе. (2 января в 13:06)
3

Если ваш исходный и целевой каталог имеют одинаковые имена, даже если целевой каталог существует, вы можете просто набрать:

cp -R /etc/skel /home/

Это скопирует каталог/etc/skel в/home /, включая скрытые файлы и каталоги.

В конце концов, вы можете скопировать каталог и переименовать его в одну строку:

cp -R /etc/skel /home/ && mv /home/skel /home/user

Или вы можете просто использовать cp -r/etc/skel/home/user для переименования skel в user ... ( 13 сентября '13 в 12:46)

Это верно, только если/home/user еще не существует. (14 октября '13 в 11:52)
2

rsync это хорошо, но другой выбор:

cp -a src/ dst/

Из основной справки:

   -a, --archive
          same as -dR --preserve=all

   -d     same as --no-dereference --preserve=links

   -R, -r, --recursive
          copy directories recursively

Я всегда использовал cp -r. Спасибо за упоминание cp -a (19 июня '17 в 18:40)
2

Вы можете использовать rsync.

rsync -aP ./from/dir/ /some/other/directory/

Вы даже можете скопировать через SSH

rsync -aP ./from/dir/ username@remotehost:/some/other/directory/

Существуют различные флаги, которые вы можете использовать: -a, --archive # archive (-rlptgoD)

-r, --recursive
-l, --links      # copy symlinks as links
-p, --perms      # preserve permissions
-t, --times      # preserve times
-g, --group      # preserve group
-o, --owner      # preserve owner
-D               # --devices --specials

--delete         # Delete extra files

You may want to add the -P option to your command.

--partial        # By default, rsync will delete any partially transferred file if the transfer is interrupted. In some circumstances it is more desirable to keep partially transferred files. Using the --partial option tells rsync to keep the partial file which should make a subsequent transfer of the rest of the file much faster.

-P               # The -P option is equivalent to --partial --progress.  Its  purpose  is to make it much easier to specify these two options for a long transfer that may be interrupted.

Страница руководства Rsync

1

Обратите внимание, что есть хитрость командной строки (работает, по крайней мере, в sh, bash и ksh ): просто добавьте суффикс к каталогу from. Это выльет содержимое каталога from в каталог to (по иронии судьбы я впервые узнал об этом приеме при использовании rsync ).

Пример:

/tmp$ mkdir test_dir1
/tmp$ cd test_dir1/
/tmp/test_dir1$ touch aa
/tmp/test_dir1$ touch .bb
/tmp/test_dir1$ cd ..
/tmp$ mkdir test_dir2

/tmp$ cp -r test_dir1/* test_dir2
/tmp$ ls -1a test_dir2
.
..
aa

/tmp$ cp -r test_dir1/ test_dir2
/tmp$ ls -1a test_dir2
.
..
.bb
aa
1

Я пришел сюда с Googled для решения той же проблемы, а потом понял, что это легко сделать с помощью find. Преимущество это не зависит от оболочки или специальных утилит, которые могут быть не установлены.

find /etc/skel/ -mindepth 1 -exec cp -r {} /home/username/ \;

Я попробовал трюк с косой чертой, но это не сработало для меня.

1

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

yes | cp -rvp /source/directory /destination/directory/

yes для автоматической перезаписи файлов назначения, r рекурсивный, v подробный, p сохранить права.

Обратите внимание, что исходный путь не заканчивается на / (поэтому все файлы/каталог и. Файлы копируются)

Каталог назначения заканчивается знаком / поскольку мы помещаем содержимое исходной папки в место назначения в целом.

1

Самый простой способ это:

cp -r /etc/skel/{.,}* /home/user

Выражение {.,}* Включает все файлы и каталоги (также начинающиеся с точки).

Если вы не хотите использовать вышеприведенное выражение, вы можете использовать свойство cp, которое позволяет указывать несколько источников для одной целевой папки:

cp -r /etc/skel/* /etc/skel/.* /home/user

при этом пропускаются такие файлы, как .. что-нибудь или ... что-нибудь и т. д. - stackoverflow.com/a/31438355/2351568 содержит правильное регулярное выражение для этой проблемы. || но в любом случае использование shopt -s dotglob все еще является лучшим решением! (6 сентября '18 в 17:53)

@DJCrashdummy, к сожалению, я не понимаю, почему вы написали свое внимание. В конце концов, мое решение учитывает случаи, о которых вы пишете. С уважением (6 сентября '18 в 22:30)

извините неправильный текст! - проблема с вашим ответом состоит в том, что он также учитывает . и .. (что эквивалентно текущей и содержащей ее папке). || , но все же ответ в ссылке объясняет это далее и предлагает решение. (7 сентября '18 в 16:23)
-2

Начиная как минимум с K3b 2.0.3, при добавлении каталога в проект появляется окно вопроса, в котором задается вопрос, хотите ли вы включить скрытые файлы ... также появляется вопрос, который нужно задать о включении ссылки. Хорошие вещи!

«всплывающее окно с вопросом» - для команды оболочки (CLI)? (15.12.16 в 1:02)

Дополнить ответ