Kopieren Sie den Verzeichnisinhalt mit dem Befehl 'cp'


33

Wie kopieren Sie den gesamten Inhalt eines Verzeichnisses in ein anderes?

Beispielsweise:

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

Das Problem mit dem oben genannten ist, dass das Globing-Muster '*' mit den versteckten Verzeichnissen '' übereinstimmt. und '..' und Sie erhalten ein Verzeichnis 'olduser' innerhalb 'newuser' sowie den Inhalt.

Sie könnten auch so etwas tun:

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

Was aber, wenn newuser bereits einige Standarddateien und -verzeichnisse enthält?

Was ist die einfachste, korrekteste, am einfachsten zu merkende und nicht verspielte Methode, um den Inhalt eines Verzeichnisses mit dem einfachen Befehl 'cp' und der Shell in ein anderes zu verschieben?

Antworten:


31

Versuchen:

cp -ra /backup/olduser/. /home/newuser

Das ist großartig, aber ich kann nicht genau herausfinden, wie es funktioniert. Ich denke, es liegt wahrscheinlich daran, dass ich nicht verstehe, wie .und wie ... Möchtest du das erklären?
Bradley.ayers

Das hat bei mir cp -r ./a bfunktioniert , aber nicht. Irgendeine Idee warum?
Brig

3
funktioniert auch bei mir, aber die roption wird nicht benötigt. Die aOption impliziert r.
MountainX

1
Der Parameter -r scheint an dieser Stelle etwas redundant zu sein!
Meister der Feier

Der -aParameter hilft in dieser Situation nicht weiter. Der Befehl cp -r ./a/. bkopiert den Inhalt und nur den Inhalt des Verzeichnisses ain das Verzeichnis b. Die -aFlagge behält Links, Zeitstempel usw. bei, was für die Frage nicht relevant ist.
Steen Schütt

23

Zwei Verzeichnisse a und b.

Beide haben Dateien in.

Sie befinden sich in einem Verzeichnis, das a und b enthält.

cp -r ./a b

-r = rekursiv.


Wollen Sie nicht, dass alle Dateien abgerufen werden?
Mittwoch,

7
Das Argument -a hat nichts mit allen Dateien zu tun, es ist eine Abkürzung für Archivierung, es bewahrt den Dateibesitz, die Berechtigungen, die Zugriffszeiten usw. Das Argument -a (obwohl es äußerst nützlich ist) ist keine Standardoption, und einige CP-Implementierungen werden nicht verwendet nicht zur Verfügung stellen.
theotherreceive

1
@mch: Wird automatisch eingefügt, da Sie aufgefordert haben cp, ein Verzeichnis zu kopieren a, und a/.somedotfileist in enthalten a. Wenn bvorhanden, erstellt dieser Befehl eine exakte Kopie von aat b/a.
Quack Quijote

2
Einfacher Weg:cp -R /some/dir/* /another/dir
Nr.

1
Dies kopiert a / foo nach b / a / foo anstatt nach b / foo
Sparr

19

Denken Sie daran, dass standardmäßig cpdas erste Verzeichnis in das zweite Verzeichnis kopiert wird, falls das zweite vorhanden ist.

Zum Beispiel cp -r a bkopiert das Verzeichnis a in b. Falls bnicht vorhanden, wird es mit dem Inhalt von erstellt a.

Wenn Sie den Inhalt von ain kopieren möchten b(zum Beispiel, wenn Sie ein gesamtes Dateisystem in einen Mount-Punkt kopieren), verwenden Sie:

cp -r a/. b

wie in der vorherigen Antwort.

Beachten Sie auch, dass -ain einigen anderen Antworten die gleichen -dr --preserve=allInformationen verwendet werden wie in Zeitstempeln, Kontext und erweiterten Attributen.


Wie funktioniert die /.Arbeit?
Bradley.ayers

a/.Stellt den Inhalt des Verzeichnisses 'a' im Gegensatz zum Verzeichnis selbst dar. In den meisten Fällen handelt es sich um ein Synonym, bei der Verwendung cp -rwird jedoch das Standardverhalten von cp vermieden (Kopieren von INTO b).
Nicolas Bonnefon

Super Tipp, das ist genau das, wonach ich gesucht habe, aber woanders nicht gefunden habe - all das 'foo / *' oder '-r foo /', was in Eckfällen fehlschlägt.
Teneriffa

@TimoHuovinen '.' ist überhaupt keine Wildcard. Es ist buchstäblich das "Eltern" -Verzeichnis, und ".." ist der Großelternteil. Dies bedeutet '/foo/./././././.' ist dasselbe Verzeichnis wie '/ foo' und '/ foo / bar / ..' ist dasselbe Verzeichnis wie '/ foo'. Stellen Sie sich diese als Hardlinks vor, die in das Dateisystem integriert sind.
Quuxman

@quuxman danke, mir war das damals nicht bewusst. Ich werde meinen alten Kommentar entfernen, um die Leute nicht zu verwirren.
Timo Huovinen

6

Wenn Sie Ihre Shell nicht ernsthaft neu konfiguriert haben, stimmt das Muster '*' nicht mit 'überein.' oder '..', wie Sie nur mit echo * überprüfen können. Stattdessen werden Dateien ausgelassen, deren Name mit einem '.' Beginnt, sodass bei Ihrem Ansatz alle versteckten Dateien fehlen. Sie können einige dieser Verhaltensweisen mit Shell-Optionen optimieren, z. B. die Option dotglob in bash. In diesem Fall ist dies jedoch nicht die portable und robuste Option, nach der Sie suchen.

Wenn Sie dies mehr als ein- oder zweimal tun müssen, empfehle ich, dass Sie sich mit rsync oder unisono (je nach spezifischen Anforderungen) und sorgfältig ausgearbeiteten Quell- und Zielspezifikationen befassen.

Eine andere Alternative besteht darin, das Quellverzeichnis in einem Tarball abzulegen und es über dem vorhandenen Zielverzeichnis zu entpacken.


1
Ich benutze dies: ( cd /src/dir ; tar cf - . ) | ( cd /dest/dir ; tar xf - )... der tar cf - .Teer ist das Quellverzeichnis, einschließlich der Punktedateien, und spuckt es zu STDOUT, das an die STDIN des weitergeleitet wird tar xf -.
Quack Quijote

Ich denke, der springende Punkt des OP ist, wie man Dateien referenziert, die mit '.' Beginnen. aber nicht das besondere '.' und '..' Verzeichnisse. Es gibt oben eine weitaus elegantere Lösung, anstatt rsync oder ein anderes komplexes Programm zu verwenden.
Quuxman

2

Dadurch werden sowohl die normalen als auch die ausgeblendeten Dateien kopiert, wobei das übergeordnete Verzeichnis ( ..) ausgeschlossen wird:

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

Wenn Sie das übergeordnete Verzeichnis nicht ausschließen, erhalten Sie auch den gesamten Inhalt ..Ihres Zielverzeichnisses.


1
Dies schließt jedoch Namen aus, die mit .. (z . B. ...oder ..super-hidden) beginnen.
Scott

0

Um Dateien zu kopieren, die mit einem Punkt beginnen, führen Sie einfach cp. * Target / aus.

Am einfachsten ist es, den Befehl cp zweimal auszuführen.

Wie Peter Eisentraut sagt, beinhalten die normalen Spielregeln nicht .. und. (hm, wie soll ich diesen Satz beenden?)

Verwenden Sie einfach -r, um es rekursiv zu machen, und -i, um cp zu veranlassen, zu fragen, ob Sie eine Datei wirklich überschreiben möchten.

cp -ri /backup/olduser/* /newuser/
cp -ri /backup/olduser/.* /newuser/

Normalerweise *passt nicht .oder .., aber es funktioniert, wenn Sie verwenden .*. Versuchen Sie es echo .*. Sie können ausschließen .und ..mit dem folgenden Muster: .[^.]*.
7.

@mch: Schließt aber .[^.]*immer noch Namen aus, die mit .. (zB ...oder ..super-hidden) beginnen.
Scott

0

Dies funktioniert zum rekursiven Kopieren aller Dateien und Verzeichnisse mit Ausnahme der versteckten Verzeichnisse aus dem aktuellen Verzeichnis an einen beliebigen Ort:

cp -rf * ^.* 
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.