Скопіюйте вміст каталогу за допомогою команди 'cp'


33

Як ви копіюєте весь вміст одного каталогу в інший?

Наприклад:

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

Проблема вищезазначеного полягає в тому, що шаблон глобалізації '*' відповідає прихованим каталогам '.' і "..", і ви закінчуєте каталог "olduser" всередині "newuser", а також вміст.

Ви також можете зробити щось подібне:

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

Але що робити, якщо newuser вже містить деякі файли та каталоги за замовчуванням?

Який найпростіший, найправильніший, найпростіший запам'ятовуючий спосіб, а не безлад для переміщення вмісту одного каталогу в інший, використовуючи лише основну команду 'cp' та оболонку?

Відповіді:


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.

В обох є файли в.

Ви знаходитесь в каталозі, який містить a і b.

cp -r ./a b

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


Ви не хочете - отримати всі файли?
bw

7
Аргумент -a не має нічого спільного з усіма файлами, він є коротким для архіву, він буде зберігати право власності на файли, дозволи, час доступу тощо. Аргумент -a (хоча дуже корисний) не є стандартним варіантом, і кілька реалізацій cp не не надаю.
theterreceive

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 /», яке не вдається в кутових випадках.
Тенер

@TimoHuovinen '.' - це зовсім не майна. Це буквально "батьківський" каталог, а ".." - це бабуся і дідусь. Це означає "/foo/./././././/". є тим самим каталогом, що і '/ foo', а '/ foo / bar / ..' - той самий каталог, що і '/ foo'. Розглядайте їх як жорсткі посилання, вбудовані у файлову систему.
quuxman

@quuxman дякую, я тоді не знав про це. Я видалю старий коментар, щоб не заплутати людей.
Тімо Хуовінен

6

Якщо ви серйозно не переконфігурували свою оболонку, шаблон "*" не відповідає "." або "..", як ви можете перевірити, використовуючи просто echo *. Натомість це робити - це опустити файли, ім’я яких починається з ".", Тому ваш підхід пропустить усі приховані файли. Ви можете налаштувати частину такої поведінки за допомогою параметрів оболонки, наприклад, опції dotglob у bash, але це не буде портативним та надійним варіантом, який ви шукаєте.

Якщо вам потрібно зробити це більше одного або двох разів, я рекомендую заглянути в rsync або унісон (залежно від конкретних потреб) з ретельно продуманими джерелами та цільовими специфікаціями.

Інша альтернатива - помістити вихідний каталог у тарбол та відміняти його за існуючим цільовим каталогом.


1
Я використовую це: ( cd /src/dir ; tar cf - . ) | ( cd /dest/dir ; tar xf - )... tar cf - .tar - це вихідний каталог, включені дотфайли, і пересилає його в STDOUT, який потрапляє в STDIN tar xf -.
кихат-шарлатан

Я думаю, що вся суть програми полягає в тому, як посилатися на файли, які починаються з "." але не спеціальне "." та довідники "..". Вище є набагато більш елегантне рішення замість використання 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/

Зазвичай *не відповідає .або .., але це робиться, якщо ви використовуєте .*. Спробуйте echo .*. Ви можете виключити .і ..до такої схеми: .[^.]*.
mch

@mch: Але .[^.]*все ж виключає імена, які починаються з .. (наприклад, ...або ..super-hidden).
Скотт

0

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

cp -rf * ^.* 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.