Скопируйте содержимое каталога с помощью команды cp

33

Как вы копируете все содержимое одного каталога в другой?

Например:

$ cd /home/newuser
$ cp -a /backup/olduser/* .

Проблема с вышесказанным заключается в том, что шаблон «*» соответствует скрытым каталогам. и '..', и вы получите каталог 'olduser' внутри 'newuser', а также его содержимое.

Вы также можете сделать что-то вроде этого:

$ rmdir /home/newuser
$ cp -a /backup/olduser /home/newuser

Но что, если newuser уже содержит некоторые файлы и каталоги по умолчанию?

Какой самый простой, самый правильный, самый простой для запоминания и не запутанный способ переместить содержимое одного каталога в другой, используя только простую команду 'cp' и оболочку?

Der Hochstapler
источник

Ответы:

31

Пытаться:

cp -ra /backup/olduser/. /home/newuser
Нагул
источник
Это здорово, но я не могу понять, как именно это работает. Я думаю, что это, вероятно, потому что я не понимаю, как .и ..работать. Хотите объяснить?
bradley.ayers
Это сработало для меня, но cp -r ./a bне сработало. Есть идеи почему?
Бриг
3
у меня тоже работает, но rопция не нужна. aВариант подразумевает r.
MountainX
1
параметр -r кажется немного избыточным на данный момент!
Мастер празднования
-aПараметр не делает ничего , чтобы помочь в этой ситуации. Команда cp -r ./a/. bскопирует содержимое каталога и только содержимое каталога aв каталог b. В -aфлаг консервы ссылки, метки времени и т.д., которая не имеет отношения к вопросу.
Стин Шютт
23

Две директории а и б.

У обоих есть файлы в.

Вы находитесь в каталоге, который содержит a и b.

cp -r ./a b

-r = рекурсивно

Рич Брэдшоу
источник
Разве вы не хотите -a получить все файлы?
мт
7
Аргумент -a не имеет ничего общего со всеми файлами, он короток для архива, он сохранит владение файлами, права доступа, время доступа и т. Д. Аргумент -a (хотя и очень полезный) не является стандартным вариантом, и некоторые реализации cp не не предоставлю это.
другой прием
1
@mch: автоматически включается, потому что вы сказали cpскопировать каталог a, и a/.somedotfileон содержится в a. если bсуществует, эта команда создаст точную копию aв b/a.
Квик-кихот
2
Простой способ:cp -R /some/dir/* /another/dir
n0pe
1
Это копирует a / foo в b / a / foo, а не в b / foo
Sparr
19

Помните, что по умолчанию cpкопируется первый каталог во второй каталог, если второй существует.

Например cp -r a b, скопировать каталог a в b. Если bне существует, он будет создан с содержанием a.

Если вы хотите , чтобы скопировать содержимое из aв b(например , при копировании всей файловой системы в точке монтирования) использование:

cp -r a/. b

как в предыдущем ответе.

Обратите также внимание, что -aв некоторых других ответах используется то же самое, что -dr --preserve=allи метки времени, контекст и расширенные атрибуты.

Николас Боннефон
источник
Как /.работает?
bradley.ayers
a/.представляет содержимое каталога 'a' в отличие от самого каталога, в большинстве случаев он является синонимом, но при использовании cp -rон избегает поведения cp по умолчанию (копирование INTO b).
Николас Боннефон
удивительный совет, это именно то, что я искал, но не смог найти в другом месте - все те «foo / *» или «-r foo /», которые не выполняются в угловых случаях.
Tener
@TimoHuovinen '.' вообще не подстановочный знак. Это буквально «родительский» каталог, а «..» является прародителем. Это значит «/foo/./././././.» это тот же каталог, что и / foo, а / foo / bar / .. это тот же каталог, что и / foo. Думайте о них как о жестких ссылках, встроенных в файловую систему.
quuxman
@ Quuxman спасибо, я не знал об этом тогда. Я уберу свой старый комментарий, чтобы не запутывать людей.
Тимо Хуовинен
6

Если вы серьезно не перенастроили свою оболочку, шаблон '*' не соответствует '.' или «..», как вы можете проверить, используя только echo *. Вместо этого он пропускает файлы, имя которых начинается с «.», Поэтому ваш подход пропустит все скрытые файлы. Вы можете настроить некоторые из этих параметров с помощью параметров оболочки, например, параметра dotglob в bash, но тогда он не будет переносимым и надежным вариантом, который вы ищете.

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

Другая альтернатива - поместить исходный каталог в tar-архив и распаковать его поверх существующего целевого каталога.

Питер Айзентраут
источник
1
я использую это: ( cd /src/dir ; tar cf - . ) | ( cd /dest/dir ; tar xf - )... tar cf - .tar является исходным каталогом, включая dotfiles, и сплит его в STDOUT, который передается по каналу STDIN tar xf -.
шарлатан Quixote
Я думаю, что весь смысл OP в том, как ссылаться на файлы, начинающиеся с '.' но не особый "." и «..» каталоги. Выше приведено гораздо более элегантное решение вместо использования rsync или какой-либо другой сложной программы.
quuxman
2

Это скопирует как нормальные, так и скрытые файлы, исключая родительский каталог ( ..):

cd /directory/to/copy
cp -r * .[^.]* /destination/directory

Если вы не исключите родительский каталог, вы также получите все содержимое ..каталога назначения.

МЧ
источник
1
Но это все еще исключает имена, начинающиеся с .. (например, ...или ..super-hidden).
Скотт
0

Чтобы скопировать файлы, начинающиеся с точки, просто выполните команду cp. * Target /

Так что проще всего сделать команду cp два раза.

Как говорит Питер Айзентраут, нормальные правила не включают ... и. (хм, как закончить это предложение?;)

Просто используйте -r, чтобы сделать его рекурсивным, и -i, чтобы cp спросил, действительно ли вы хотите перезаписать файл.

cp -ri /backup/olduser/* /newuser/
cp -ri /backup/olduser/.* /newuser/
gaqzi
источник
Обычно *не соответствует .или .., но это не так, если вы используете .*. Попробуй echo .*. Вы можете исключить .и ..со следующей схемой: .[^.]*.
МЧ
@mch: Но .[^.]*все равно исключаются имена, начинающиеся с .. (например, ...или ..super-hidden).
Скотт
0

Это работает для копирования всех файлов и каталогов, за исключением рекурсивных скрытых каталогов из текущего каталога в любое место:

cp -rf * ^.* 
Seeeve
источник