Wie kopiere ich mit cp, wenn der Zielordner bereits vorhanden ist?

8

Beispiel...

Das ist was ich will.

/tmp $ cp -f -R --verbose /tmp/a /tmp/b
`/tmp/a' -> `/tmp/b'
`/tmp/a/file2' -> `/tmp/b/file2'
`/tmp/a/file1' -> `/tmp/b/file1'

Das will ich nicht.

/tmp $ cp -f -R --verbose /tmp/a /tmp/b
`/tmp/a' -> `/tmp/b/a'
`/tmp/a/file2' -> `/tmp/b/a/file2'
`/tmp/a/file1' -> `/tmp/b/a/file1'

Wie kann ich cp so verhalten lassen, als ob der Ordner noch nicht existiert hätte?

(Ich möchte es nicht vorher löschen. Nur einige Dateien aus / tmp / a, um in / tmp / b kopiert zu werden, ohne einen Unterordner a in / tmp / b zu erstellen. Es sieht also aus wie / tmp / b / file1 / tmp / b / file2 und so weiter.)

James Mitch
quelle
Wenn dies der echte James Mitch ist, der dies gepostet hat, sagen Sie dies bitte in diesem Kontenprofil;)
James Mitch
Was passiert, wenn ich oder jemand anderes, der dieses Konto verwendet, niemals eine Antwort akzeptiert? Wird "ich" immer noch diese 100 Reputationspunkte verlieren?
James Mitch
Ja du würdest. Siehe dies: askubuntu.com/users/72629/james-mitch?tab=reputation Der Repräsentant wird sofort abgezogen, wenn er ein Kopfgeld platziert.
0xC0000022L

Antworten:

3

Rsync wurde für solche Dinge erfunden.

rsync -av --update /source/ /destination

NB: Beachten Sie, dass / source / ein abschließendes "/" hat, das Datei1, Datei2 und nicht den Ordner aufnimmt, in dem es sich befindet. / Destination hat kein abschließendes. Ihre Lösung sieht also so aus:

rsync -av --update /tmp/a/ /tmp/b
root-11
quelle
2
Die Leute benutzen es so, aber es wurde für die Netzwerkübertragung erfunden. Wenn Sie Gigabyte an Dateien lokal kopieren, ist dies möglicherweise einige Male langsamer. Einige Messungen hier: lwn.net/Articles/400489
sourcejedi
Wenn Sie verwenden, -Wwird die rsyncÜberprüfung auf Unterschiede übersprungen, um die Leistung zu verbessern.
Muru
9

Die -TFlagge (AKA --no-target-directory) macht was Sie wollen:

$ cp -R --verbose -T /tmp/a /tmp/b
`/tmp/a/file1' -> `/tmp/b/file1'
`/tmp/a/file2' -> `/tmp/b/file2'
Flimm
quelle
5

Vorausgesetzt, Bash können Sie tun

( shopt -s dotglob; cp -f -R --verbose /tmp/a/* /tmp/b/ )

Was dies tut ist:

  1. Dadurch wird sichergestellt, dass Globs (die *) Dateien mit einem Punkt vor ihnen abfangen. Sie werden durch Konvention als "versteckt" betrachtet.
  2. *wird erweitert, bevor cpder Befehl angezeigt wird. Wenn es also zwei Dateien gibt, wie in Ihrer Frage, wird die erweiterte Befehlszeile angezeigtcp -f -R --verbose /tmp/a/file1 /tmp/a/file1 /tmp/b/
  3. Schließlich stellt der nachfolgende Backslash am Ziel sicher, dass es in diesen Ordner kopiert wird /tmp/b/.

Diese Methode stellt auch sicher, dass Sie die Shell-Option nicht zurücksetzen müssen, da sie in einer Subshell ausgeführt wird. Sie können ähnliche Ergebnisse erzielen, indem Sie sie in eine Skriptdatei einfügen, anstatt sie über die Befehlszeile auszuführen.

0xC0000022L
quelle
1
$ cp -r --verbose a/. b
`a/.' -> `b'
`a/./zzz' -> `b/zzz'

$ cp -r --verbose a/. b
`a/./zzz' -> `b/./zzz'

Ich glaube nicht, dass ich das irgendwo beschrieben gesehen habe; Ich habe nur verschiedene Möglichkeiten ausprobiert und eine gefunden, die funktioniert. Soweit ich weiß, ist dies eine natürliche Folge davon, wie /.und wie cp. (Im Gegensatz zu der rsyncin einer anderen Antwort erwähnten Syntax für , die ausdrücklich als Sonderfall dokumentiert ist).

sourcejedi
quelle