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

322330
eleven81

Как я могу сделать cp -rкопию абсолютно всех файлов и каталогов в каталоге

Требования:

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

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

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

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

320
Здесь больше ответов, хотя они выглядят не так хорошо; http://serverfault.com/questions/3154/recursively-copying-hidden-files-linux/ Roel Van de Paar 8 лет назад 1
Пожалуйста, Eleven81, подумайте об изменении принятого ответа на ответ, данный @bruno pereira, потому что он избегает создания новой папки. Если нет, то пусть этот комментарий будет предупреждением для новых читателей, чтобы проверить также другой (наиболее проголосовавший) ответ. Tx. Dr Beco 8 лет назад 0

13 ответов на вопрос

409
Bruno Pereira

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

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

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

Если я не ошибаюсь, это не копирует скрытые / точечные файлы. Halil Özgür 11 лет назад 4
Хорошо работает для меня. Обратите внимание, что "." имеет решающее значение для его работы. Mark 11 лет назад 25
Это работает, но почему? Не могу найти ссылку на это в руководстве. Julien Palard 10 лет назад 11
Это лучший ответ на то, что мне было нужно и, вероятно, многим другим. Kristopher Ives 10 лет назад 0
Я думаю, что это работает, потому что обычно это создает новую папку с именем последней папки в первом аргументе. Однако, так как это имя `.`, такое поведение потребует от него создания уже существующего каталога, поэтому он просто пропускает этот шаг. Zenexer 10 лет назад 5
Считается, что редактирование, но будет комментировать, чтобы дать больше возможностей для обзора. Я думаю, что должна быть третья командная строка, говорящая `chown -R: /Главная/`передать права собственности на файлы новому пользователю. Pavel Šimerda 9 лет назад 0
Ну, я не согласен, текущий ответ является правильным для вопроса. Вам также необходимо отредактировать заголовок вопроса (и сам вопрос), чтобы сопоставить предлагаемое изменение с этим ответом. Bruno Pereira 9 лет назад 0
Ну, это никогда не плохо, если ответ лучше, чем вопрос. Может быть в отдельной заметке. Если вы этого не сделаете, вы получите нерабочий, что может удивить, потому что системные инструменты, которые копируют скелет, автоматически проверяют правильность владения. Я бы даже сказал, что это решение вопроса, но оно * создает * новую проблему на пути, которую он не решает. Pavel Šimerda 9 лет назад 0
Обратите внимание, что ответы предназначены не только для ОП, но и для всех, кто находит страницу через веб-поиск. Pavel Šimerda 9 лет назад 0
Причина, по которой это работает, в том, что он эквивалентен `cp -r / etc / skel / home /`. Точка `.` является именем, эквивалентным оболочке для" _This directory_ ", точно так же, как двойная точка` ..` означает "_Go up one directory_" относительно заданного пути. Это относительный указатель пути. Попробуйте это: `ls -d / etc / skel / .` Вы должны увидеть, что bash` eval`s this to: `/ etc / skel / .` Если вы попробуете` ls -l / home // .`, вы увидите файлы в `/ home /` TrinitronX 9 лет назад 1
@BrunoPereira: Спасибо! Ваше решение сработало для меня, но мне любопытно узнать, почему используется "." (точка) копирует скрытый файл. Technext 8 лет назад 0
Hy @Technext, объяснение от TrinitronX, кажется, на месте: не мог объяснить это лучше сам. Bruno Pereira 8 лет назад 0
Хммм ... я прочитал его комментарий, но был смущен, почему * не работает. Кажется * соответствует всем, кроме точечных (.) Файлов. Technext 8 лет назад 0
@Technext Глобализация по умолчанию в bash не включает имена файлов, начинающиеся с `.`, чтобы изменить то, что вам нужно использовать команду` shopt -s dotglob`, чтобы иметь возможность включать эти файлы. Таким образом, с `*` по умолчанию вы запрашиваете рекурсивное копирование всех файлов из этого каталога, который может быть расширен с помощью `*` (по умолчанию скрытые файлы не включены). На другом конце с `.` вы используете cp для рекурсивного копирования всего из« этого каталога ». Bruno Pereira 8 лет назад 21
@ BrunoPereira: Большое спасибо за объяснение! :) Теперь все понятно. :) Technext 8 лет назад 0
Это должен быть принятый ответ Drew 7 лет назад 0
@JulienPalard [У нас наконец есть ответ на это!] (Https://unix.stackexchange.com/a/409227/67771) iFreilicht 6 лет назад 1
229
Randy Orrison

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

cp -r /etc/skel /home/user

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

Можно ли использовать нечто подобное, если `/ home / user / skel` * существует *? bradley.ayers 13 лет назад 48
@ bradley.ayers Я думаю, что можно скопировать во временный подкаталог, а затем переместить их на верхний уровень (так как перемещение на одном диске происходит быстро). Менее чем идеал, но короче, чем другие решения для меня. Halil Özgür 11 лет назад 0
@ bradley.ayers Ответ Бруно ниже отвечает на ваш вопрос Mark 11 лет назад 7
Это решение не сработало для меня. Он не копировал скрытые файлы. Я использую CentOS релиз 6.5. Решение @ Бруно сработало. Technext 8 лет назад 1
В Ubuntu / Debian это помещает каталог 'skel' в целевой каталог, а не рекурсивные файлы внутри skel. Для правильного использования используйте `-T` (без цели). (`-rT` для рекурсивного) bshea 7 лет назад 2
Это не копирует скрытые (точечные) файлы, такие как .profile или .bashrc Drew 7 лет назад 0
Если `/ home / user` существует, то это скопирует содержимое` / etc / skel` без создания `/ home / user / skel`:` find / etc / skel -type f -exec cp {} / home / пользователь \; ` Ralph Bolton 7 лет назад 0
** Осторожно **, что это не сохраняет атрибуты файла по умолчанию. Поэтому убедитесь, что вы добавили свою комбинацию меток времени / xattr / etc. через -p / - флаг сохранения! (сравните справочную страницу) isync 6 лет назад 0
63
PersianGulf

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 
Это полезно, когда вы хотите скопировать только содержимое, не создавая новый каталог в месте назначения. Особенно, когда пункт назначения является точкой монтирования. kaszynek 11 лет назад 2
Это действительно лучший ответ и доходит до сути вопроса .. Stephen 10 лет назад 3
Это `setopt` для Zsh, на случай, если кому-то еще интересно. Pat 9 лет назад 6
54
TechnocratiK

The correct means of doing this is to use the -T (--no-target-directory) option, and recursively copy the folders (without trailing slashes, asterisks, etc.), i.e.:

cp -rT /etc/skel /home/user 

This will copy the contents of /etc/skel to /home/user (including hidden files), creating the folder /home/user if it does not exist; however the -T option prevents the contents of /etc/skel from being copied to a new folder /home/user/skel should the folder /home/user exist.

Правильный ответ. +1 bshea 7 лет назад 2
это был действительно правильный ответ Gaetan 6 лет назад 0
это ЛУЧШИЙ ответ из группы; это единственный, который решает проблему, не усложняя ее ZaxLofful 6 лет назад 0
23
user1084282

Use rsync:

rsync -rtv source_folder/ destination_folder/

3
Gabriel Hautclocq

If your source and target directory have the same name, even if target directory exists, you can simply type:

cp -R /etc/skel /home/ 

This will copy the /etc/skel directory into /home/, including hidden files and directories.

Eventually, you can copy the directory and rename it in a single line :

cp -R /etc/skel /home/ && mv /home/skel /home/user 
Или вы можете просто использовать `cp -r / etc / skel / home / user` для переименования` skel` в `user` ... David 11 лет назад 0
Это верно, только если / home / user еще не существует. Gabriel Hautclocq 11 лет назад 0
2
Wink Saville

rsync is good, but another choice:

cp -a src/ dst/ 

From the main help:

 -a, --archive same as -dR --preserve=all -d same as --no-dereference --preserve=links -R, -r, --recursive copy directories recursively 
Я всегда использовал cp -r. Спасибо за упоминание cp -a Pinaki Mukherjee 7 лет назад 0
2
RoshP

You could use rsync.

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

You can even copy over ssh

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

There are various flags you can use: -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 man page

1
Dustin Oprea

Обратите внимание, что есть хитрость командной строки (работает, по крайней мере, в 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
Linus

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

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

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