Was ist der Mehrwert der Option -T in GNU cp und mv?

26

Warum haben einige GNU Coreutils-Befehle die -T/--no-target-directoryOption? Es scheint, dass alles, was es tut, mit der Semantik von .(self dot) in einer traditionellen Unix-Verzeichnishierarchie erreicht werden kann.

In Anbetracht:

cp -rT /this/source dir

Die -TOption verhindert, dass die Kopie ein dir/sourceUnterverzeichnis erstellt. Vielmehr /this/sourcewird mit identifiziert dirund der Inhalt entsprechend zwischen den Bäumen abgebildet. So /this/source/foo.cgeht zum Beispiel zu dir/foo.cund so weiter, anstatt zu dir/source/foo.c.

Dies kann jedoch problemlos ohne die folgende -TOption erreicht werden:

cp -r /this/source/. dir  # Probably worked fine since dawn of Unix?

Semantisch wird die abschließende Punktkomponente als Kind von kopiert dir, aber natürlich existiert dieses "Kind" bereits (muss also nicht erstellt werden) und ist tatsächlich dirselbst, so dass der Effekt derjenige /this/pathist, mit dem identifiziert wird dir.

Es funktioniert einwandfrei, wenn das aktuelle Verzeichnis das Ziel ist:

cp -r /this/tree/node/. . # node's children go to current dir

Gibt es etwas , können Sie tun , nur mit , -Tdass seine Existenz rationalisieren? (Neben der Unterstützung für Betriebssysteme, die das Punktverzeichnis nicht implementieren, eine Begründung, die in der Dokumentation nicht erwähnt wird.)

Löst der obige Punkttrick nicht die gleichen Wettkampfbedingungen, die in der GNU Info-Dokumentation zu erwähnt sind -T?

Kaz
quelle

Antworten:

29

Ihr .Trick kann nur verwendet werden, wenn Sie ein Verzeichnis kopieren, keine Datei. Die -TOption funktioniert sowohl mit Verzeichnissen als auch mit Dateien. Wenn Sie tun:

cp srcfile destfile

und es gibt bereits ein Verzeichnis mit dem Namen, in das destfilees kopiert wird destfile/srcfile, was möglicherweise nicht beabsichtigt ist. Also benutzt du

cp -T srcfile destfile

und du bekommst den Fehler richtig:

cp: cannot overwrite directory `destfile' with non-directory

Wenn Sie es mit der .Methode versuchen würden, würde die Kopie niemals funktionieren:

cp: cannot stat `srcfile/.`: Not a directory
Barmar
quelle
Der .Trick funktioniert beim Kopieren einer Datei, nur nicht beim gleichzeitigen Umbenennen des Basisnamens! cp /path/to/file /target/dir/. Wenn /target/dir/filevorhanden und ein Verzeichnis ist, erhalten Sie die gleiche Diagnose! Aber Sie haben gezeigt, was -Tdas nicht kann, ohne es in einem Schritt und ohne Race-Bedingungen zu tun: Kopieren Sie eine Datei und ändern Sie ihren Namen, ohne dass sie in ein Unterverzeichnis verschoben wird.
Kaz
3
Das ist nicht dasselbe - der .Trick, über den Sie sprechen, hängt /.an die Quelle an .
Barmar
21

Das Problem mit cp/ mv/ lnwie sie ursprünglich entworfen wurden , ist , dass sie zwei Befehle in einer ( Kopie an und kopieren Sie in ).

cp A B

ist entweder Kopieren von A nach B oder Kopieren von A nach B ( Kopieren von A nach B / A ), je nachdem, ob Bes ein Verzeichnis gibt oder nicht (und weitere Variationen, wenn B ein Symlink zu einem Verzeichnis ist).

Das ist schlecht, weil es mehrdeutig ist. Daher haben die GNU-Implementierungen Optionen hinzugefügt, um dies zu umgehen.

cp -T A B

Kopien von A bis B unabhängig. Wenn Bvorhanden und ein Verzeichnis ist, schlägt dies fehl (es sei denn, Sie übergeben -r). In jedem Fall erhalten Sie keine ADatei, Bwenn Sie beabsichtigen A, nach B kopiert zu werden .

Und:

cp -t B A

ist die Kopie in .

Stéphane Chazelas
quelle
Die ursprüngliche Unix-Philosophie besagt, dass Sie wissen, was Sie tun, und dass Sie sich gerne in den Fuß schießen können.
Lenne
4
@Lenne, aber hier hast du keine Möglichkeit, dich nicht in den Fuß zu schießen. Wenn jemand ein B-Verzeichnis oder einen Symlink zu einem Verzeichnis erstellt, bevor Sie cp A Bden Befehl ausführen, wird nicht das getan, was Sie beabsichtigt haben. Und dabei ist [ -e B ] || [ -L B ] || cp A Bimmer noch eine Racebedingung, die cp -Tn A Bes nicht gibt.
Stéphane Chazelas
6

Dies -Tkann zu einem Fehler führen, wenn ein Verzeichnis für eine Zieldatei nicht ordnungsgemäß vorhanden ist:

$ mkdir mustbeafile
$ touch afile
$ cp -T afile mustbeafile
cp: cannot overwrite directory `mustbeafile' with non-directory
$ echo $?
1
$ cp afile mustbeafile
$ 

Dies bedeutet, dass anstelle von Erfolg beim unerwarteten Kopieren in ein Unterverzeichnis eine Warnung und ein nicht einwandfreier Beendigungsstatus angezeigt werden, die zum Abbruch eines Skripts führen können eins sein.

Thrig
quelle
0

Die Verwendung eines Flags ist auch viel klarer und birgt ein geringeres Risiko für unbeabsichtigte Auswirkungen, wenn der Befehl in einem Skript verwendet wird, anstatt manuell eingegeben zu werden. Das Patchen von Punkten auf Pfade in einem Skript kann zu unerwartetem Unheil führen.

Rackandboneman
quelle