Skopiuj zawartość katalogu za pomocą polecenia „cp”

33

Jak skopiować całą zawartość jednego katalogu do innego?

Na przykład:

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

Problem z powyższym polega na tym, że wzór globowania „*” pasuje do ukrytych katalogów ”. i „..”, a skończysz na katalogu „olduser” wewnątrz „newuser”, a także na zawartości.

Możesz także zrobić coś takiego:

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

Ale co jeśli newuser zawiera już jakieś domyślne pliki i katalogi?

Jaki jest najprostszy, najbardziej poprawny, najłatwiejszy do zapamiętania, a nie nieporządny sposób przenoszenia zawartości jednego katalogu do drugiego za pomocą prostej komendy „cp” i powłoki?

Der Hochstapler
źródło

Odpowiedzi:

30

Próbować:

cp -ra /backup/olduser/. /home/newuser
nagul
źródło
To wspaniale, ale nie mogę dokładnie zrozumieć, jak to działa. Myślę, że to prawdopodobnie dlatego, że nie rozumiem, jak .i jak ..działa. Chcesz to wyjaśnić?
bradley.ayers
To działało dla mnie, ale cp -r ./a bnie. Masz pomysł, dlaczego?
Bryg.
2
też działa dla mnie, ale ropcja nie jest potrzebna. aOpcja zakłada r.
MountainX
1
parametr -r wydaje się w tym momencie nieco redundantny!
Master of Celebration
23

Dwa katalogi a i b.

Oba mają pliki.

Jesteś w katalogu, który zawiera aib.

cp -r ./a b

-r = rekurencyjnie.

Rich Bradshaw
źródło
Czy nie chcesz -a, aby uzyskać wszystkie pliki?
mc
7
Argument -a nie ma nic wspólnego ze wszystkimi plikami, jest skrótem od archiwizacji, zachowa własność pliku, uprawnienia, czasy dostępu itp. Argument -a (choć bardzo przydatny) nie jest standardową opcją, a kilka implementacji cp nie zapewniam tego.
theotherreceive
1
@mch: automatycznie dołączany, ponieważ kazałeś cpskopiować katalog ai a/.somedotfilejest on zawarty przez a. jeśli bistnieje, to polecenie utworzy dokładną kopię pliku aat b/a.
quack quixote
2
Łatwy sposób:cp -R /some/dir/* /another/dir
n0pe
1
To kopiuje a / foo do b / a / foo zamiast do b / foo
Sparr
18

Pamiętaj też, że domyślnie cp kopiuje pierwszy katalog do drugiego katalogu, jeśli drugi istnieje. Na przykład cp -a a bskopiuje INTO b, jeśli istnieje b, tzn. Utworzy a do b.

Jeśli nie jest to, czego chcesz i chcesz skopiować zawartość a do b (na przykład podczas kopiowania całego systemu plików do punktu montowania) użyj:

cp -a a/. b

jak w poprzedniej odpowiedzi.

Należy również pamiętać, że -aobejmuje -rto -arjest zbędne.

Nicolas Bonnefon
źródło
Jak /.działa
bradley.ayers
a/.reprezentuje zawartość katalogu „a” w przeciwieństwie do samego katalogu, w większości przypadków jest synonimem, ale podczas używania cp -runika domyślnego zachowania cp (kopiowanie INTO b).
Nicolas Bonnefon,
świetna wskazówka, właśnie tego szukałem, ale nie udało mi się znaleźć gdzie indziej - wszystkie te „foo / *” lub „-r foo /”, które zawodzą w narożnych przypadkach.
Tener
@TimoHuovinen '. ” wcale nie jest symbolem wieloznacznym. Jest to dosłownie katalog „nadrzędny”, a „..” to dziadek. Oznacza to „/foo/./././././.” to ten sam katalog co „/ foo”, a „/ foo / bar / ..” to ten sam katalog co „/ foo”. Pomyśl o nich jak o dowiązaniach twardych wbudowanych w system plików.
quuxman
@quuxman dziękuję, wtedy nie byłem tego świadomy. Usunę mój stary komentarz, aby uniknąć mylących ludzi.
Timo Huovinen,
6

O ile poważnie nie zmieniłeś konfiguracji powłoki, wzór globowania „*” nie pasuje ”. lub „..”, ponieważ można to zweryfikować za pomocą echa *. Zamiast tego pomija pliki, których nazwa zaczyna się od „.”, Więc twoje podejście pominie wszystkie ukryte pliki. Możesz poprawić niektóre z tych zachowań za pomocą opcji powłoki, na przykład opcji dotglob w bash, ale wtedy nie będzie to przenośna i niezawodna opcja, której szukasz.

Jeśli musisz to zrobić więcej niż raz lub dwa razy, radzę zajrzeć do rsync lub unison (w zależności od konkretnych potrzeb) ze starannie spreparowanymi specyfikacjami źródłowymi i docelowymi.

Inną alternatywą jest umieszczenie katalogu źródłowego w archiwum tar i rozpakowanie go nad istniejącym katalogiem docelowym.

Peter Eisentraut
źródło
1
używam tego: ( cd /src/dir ; tar cf - . ) | ( cd /dest/dir ; tar xf - )... tar cf - .tar jest katalogiem źródłowym, zawiera pliki dotfiles i wypluwa go do STDOUT, który jest przesyłany do STDIN pliku tar xf -.
quack quixote
Myślę, że sednem PO jest to, jak odwoływać się do plików zaczynających się od „.” ale nie specjalne ”. i katalogi „..”. Jest o wiele bardziej eleganckie rozwiązanie powyżej zamiast używania rsync lub innego złożonego programu.
quuxman
2

Spowoduje to skopiowanie zarówno normalnych, jak i ukrytych plików, z wyłączeniem katalogu nadrzędnego ( ..):

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

Jeśli nie wykluczysz katalogu nadrzędnego, skończysz z całą zawartością ..katalogu docelowego.

mch
źródło
1
Ale nadal wyklucza to nazwy rozpoczynające się od .. (np. ...Lub ..super-hidden).
Scott
0

Aby skopiować pliki zaczynające się od kropki, po prostu wykonaj cp. * Target /

Najłatwiej jest po prostu wykonać polecenie cp dwa razy.

Jak mówi Peter Eisentraut, normalne zasady globowania nie obejmują… i. (hm, jak zakończyć to zdanie?;)

Wystarczy użyć -r, aby uczynić go rekurencyjnym, i -i, aby polecenie cp zapytało, czy naprawdę chcesz zastąpić plik.

cp -ri /backup/olduser/* /newuser/
cp -ri /backup/olduser/.* /newuser/
gaqzi
źródło
Zwykle *nie pasuje .lub .., ale tak jest, jeśli używasz .*. Spróbować echo .*. Można wykluczyć .i ..z następującym wzorem: .[^.]*.
mch
@mch: Ale .[^.]*nadal wyklucza nazwy rozpoczynające się od .. (np. ...lub ..super-hidden).
Scott
0

Działa to w przypadku kopiowania wszystkich plików i katalogów z wyjątkiem ukrytych katalogów rekurencyjnie z bieżącego katalogu do dowolnego miejsca:

cp -rf * ^.* 
Seeeve
źródło