
Frage:Ich brauche ein einfaches Beispiel für die Verwendung cp --no-target-directory
.
Ich habe einige Verständnisschwierigkeiten cp --no-target-directory
. Ich verstehedie Erklärung fürmv --no-target-directory
, aber ich kann mir nicht wirklich vorstellen, wofür man es verwenden könnte cp
.
Wenn der Befehl beispielsweise
mv /tmp/source /tmp/dest
erfolgreich ist, gibt es keine Garantie dafür, dass/tmp/source
er in umbenannt wurde/tmp/dest
: Er hätte/tmp/dest/source
stattdessen in umbenannt werden können, wenn ein anderer Prozess/tmp/dest
ein Verzeichnis erstellt hätte. Wenn er jedochmv -T /tmp/source /tmp/dest
erfolgreich ist, besteht kein Zweifel daran, dass/tmp/source was renamed to
/tmp/dest`. (Quelle)
Antwort1
Standardmäßig cp
wird geprüft, ob das letzte Argument ein vorhandenes Verzeichnis ist. Wenn dies der Fall ist, cp
wird ein Link innerhalb dieses Verzeichnisses mit dem Basisnamen der Quelle erstellt. Das heißt, bei dem Befehl
cp foo/bar wibble
Wenn wibble
es sich um ein vorhandenes Verzeichnis handelt, cp
wird die Quelle nach kopiert wibble/bar
. Wenn wibble
es nicht vorhanden ist, cp
wird die Quelle mit verknüpft wibble
.
Wenn Sie sicher sein möchten, dass die Kopie immer ist wibble
, können Sie die Option --no-target-directory
(Alias -T
) angeben. Auf diese Weise cp
können Sie sicher sein, dass die Kopie bei Erfolg aufgerufen wird wibble
. Wenn wibble
bereits als Verzeichnis vorhanden, cp
schlägt dies fehl.
In tabellarischer Form:
The target is … Without -T With -T
existing directory copy in the directory error
existing file (not dir) overwrite overwrite
does not exist create create
Der einzige Unterschied besteht darin -T
, dass der Befehl einen Fehler zurückgibt, wenn das Ziel ein vorhandenes Verzeichnis ist. Dies ist nützlich, wenn Sie davon ausgehen, dass das Verzeichnis nicht existiert: Sie erhalten eine Fehlermeldung, anstatt dass etwas Unvorhergesehenes passiert.
Dasselbe gilt für mv
und ln
. Wenn das Ziel ein vorhandenes Verzeichnis ist, -T
signalisieren sie mit einen Fehler, anstatt stillschweigend etwas anderes zu tun.
Bei cp
ist der Fall anders. Wenn Sie eine rekursive Kopie durchführen und die Quelle ein Verzeichnis ist, dann cp -T
kopiert den Inhalt der Quelle in das Ziel, anstatt die Quelle selbst zu kopieren. Das heißt, gegeben
$ tree source destination
source
└── foo
destination
└── bar
Dann
$ cp -rv source destination
`source' -> `destination/source'
`source/foo' -> `destination/source/foo'
wohingegen
% cp -rvT source destination
`source/foo' -> `destination/foo'
Antwort2
Sie verwenden --no-target-directory
, wenn Sie nicht möchten, dass ein Quellverzeichnis kopiert wirddarunterein vorhandenes Zielverzeichnis, Sie möchten das Quellverzeichnis kopierenauf zudas Zielverzeichnis.
Hier ist ein Beispiel für eine Verzeichniskopie mit und ohne --no-target-directory
:
$ mkdir a
$ touch a/b a/c
$ find
.
./a
./a/c
./a/b
$ cp -r a b # b does not exist; becomes copy of a
$ find
.
./b
./b/b
./b/c
./a
./a/c
./a/b
$ rm -r b
$ mkdir b
$ cp -r a b # b already exists; a is copied *underneath* it
$ find
.
./b
./b/a
./b/a/b
./b/a/c
./a
./a/c
./a/b
$ rm -r b
$ mkdir b
$ cp -r --no-target-directory a b # b already exists; becomes copy of a
$ find
.
./b
./b/b
./b/c
./a
./a/c
./a/b
Sie können einen ähnlichen Effekt erzielen, indem Sie den Namen des Quellverzeichnisses mit einem Schrägstrich versehen, /.
wie in: cp -r a/. b
which copys source directorya
auf zu b
und nichtdarunter b
.
Keine der oben genannten Methoden ist dasselbe wie „kopiere nur den Inhalt des Quellverzeichnisses in das vorhandene Ziel“, denn wenn du die Beibehaltung von Zeit und Berechtigungen angibst, erhält das vorhandene Zielverzeichnis die Zeit und Berechtigungen des Quellverzeichnisses. Ein Beispiel (bearbeitet, um unnötige Informationen zu entfernen):
$ find . -ls
drwx------ Oct 13 13:31 ./b # note date and permissions
drwxr-xr-x Jan 1 2013 ./a # note date and permissions
-rw-r--r-- Oct 13 13:23 ./a/c
-rw-r--r-- Oct 13 13:23 ./a/b
$ cp -rp --no-target-directory a b # preserve mode and timestamps
$ find . -ls
drwxr-xr-x Jan 1 2013 ./b # note copied date and permissions
-rw-r--r-- Oct 13 13:23 ./b/b
-rw-r--r-- Oct 13 13:23 ./b/c
drwxr-xr-x Jan 1 2013 ./a
-rw-r--r-- Oct 13 13:23 ./a/c
-rw-r--r-- Oct 13 13:23 ./a/b
Bei einer Nur-Inhalts-Kopie würden weder der Modus noch die Zeitstempel des Quellverzeichnisses in das Zielverzeichnis übertragen.
Antwort3
Wie wäre es mit Folgendem?
$ cp -rvT Dir_1 Dir_2
‘Dir_1/File_3.txt’ -> ‘Dir_2/File_3.txt’
‘Dir_1/File_1.txt’ -> ‘Dir_2/File_1.txt’
‘Dir_1/File_2.txt’ -> ‘Dir_2/File_2.txt’
$ cp -rv Dir_1 Dir_2
‘Dir_1’ -> ‘Dir_2/Dir_1’
‘Dir_1/File_3.txt’ -> ‘Dir_2/Dir_1/File_3.txt’
‘Dir_1/File_1.txt’ -> ‘Dir_2/Dir_1/File_1.txt’
‘Dir_1/File_2.txt’ -> ‘Dir_2/Dir_1/File_2.txt’
An sich ist es nur eine andere Art, zu schreiben cp Dir_1/* Dir_2/
. Es erkennt jedoch versteckte Dateien im Stammverzeichnis von Dir_1, die bei einem einfachen übersehen würden cp *
.
$ touch Dir_1/.Hidden_File_{1,2,3}.txt
$ cp -rv Dir_1/* Dir_2
cp: No match.
$ cp -rvT Dir_1 Dir_2
‘Dir_1/.Hidden_File_2.txt’ -> ‘Dir_2/.Hidden_File_2.txt’
‘Dir_1/.Hidden_File_3.txt’ -> ‘Dir_2/.Hidden_File_3.txt’
‘Dir_1/.Hidden_File_1.txt’ -> ‘Dir_2/.Hidden_File_1.txt’