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.)


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

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'

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.


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).

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.