Quelle est la valeur ajoutée de l'option -T dans GNU cp et mv?

26

Pourquoi certaines commandes GNU Coreutils ont-elles l' -T/--no-target-directoryoption? Il semble que tout ce qu'il fait peut être réalisé en utilisant la sémantique de .(self dot) dans une hiérarchie de répertoires Unix traditionnelle.

Considérant:

cp -rT /this/source dir

L' -Toption empêche la copie de créer un dir/sourcesous - répertoire. Il /this/sourceest plutôt identifié avec diret le contenu est cartographié entre les arbres en conséquence. Ainsi, par exemple, /this/source/foo.cva à dir/foo.cet ainsi de suite, plutôt qu'à dir/source/foo.c.

Mais cela peut être facilement accompli sans l' -Toption en utilisant:

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

Sémantiquement, le composant de point de fin est copié en tant qu'enfant de dir, mais bien sûr cet "enfant" existe déjà (donc n'a pas besoin d'être créé) et est en fait dirlui-même, donc l'effet /this/pathest identifié avec dir.

Cela fonctionne très bien si le répertoire courant est la cible:

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

Y at - il quelque chose que vous pouvez faire seulement avec -Tqui peut rationaliser son existence? (Outre la prise en charge des systèmes d'exploitation qui n'implémentent pas le répertoire dot, une justification non mentionnée dans la documentation.)

Le point ci-dessus ne résout-il pas les mêmes conditions de concurrence que celles mentionnées dans la documentation GNU Info -T?

Kaz
la source

Réponses:

29

Votre .astuce ne peut être utilisée que lorsque vous copiez un répertoire, pas un fichier. L' -Toption fonctionne avec les répertoires et les fichiers. Si tu fais:

cp srcfile destfile

et il y a déjà un répertoire nommé destfilevers destfile/srcfilelequel il copiera , qui peut ne pas être prévu. Vous utilisez donc

cp -T srcfile destfile

et vous obtenez correctement l'erreur:

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

Si vous essayez d'utiliser la .méthode, la copie ne fonctionnera jamais:

cp: cannot stat `srcfile/.`: Not a directory
Barmar
la source
L' .astuce fait le travail lors de la copie d' un fichier, mais pas lors du renommage son nom de base en même temps! cp /path/to/file /target/dir/. S'il /target/dir/fileexiste et qu'il s'agit d'un répertoire, vous obtenez le même diagnostic! Mais vous avez montré ce -Tque cela ne peut pas être fait sans lui en une seule étape, sans conditions de concurrence: copiez un fichier et changez son nom sans qu'il soit shunté dans un sous-répertoire.
Kaz
3
Ce n'est pas la même chose - l' .astuce dont vous parlez consiste à ajouter /.à la source .
Barmar
21

Le problème avec cp/ mv/ lncomme ils ont été initialement conçus est qu'ils sont deux commandes en une ( copier vers et copier dans ).

cp A B

est soit copier A vers B ou copier A dans B ( copier A vers B / A ) selon qu'il Bexiste et est un répertoire ou non (et plus de variantes si B est un lien symbolique vers un répertoire).

C'est mauvais parce que c'est ambigu. Les implémentations GNU ont donc ajouté des options pour contourner cela.

cp -T A B

copie A à B de toute façon . S'il Bexiste et est un répertoire, cela échouera (sauf si vous passez -r). Dans tous les cas, vous ne vous retrouverez pas avec un Afichier à l'intérieur Blorsque vous souhaitiez Aêtre copié sur B.

Et:

cp -t B A

est la copie en .

Stéphane Chazelas
la source
La philosophie originale d'Unix est de supposer que vous savez ce que vous faites et vous permettra avec plaisir de vous tirer une balle dans le pied.
Lenne
4
@Lenne, mais ici, cela ne vous permet pas d'éviter de vous tirer une balle dans le pied. Si quelqu'un crée un répertoire B ou un lien symbolique vers un répertoire juste avant d'exécuter, cp A Bla commande ne fera pas ce que vous vouliez. Et faire a [ -e B ] || [ -L B ] || cp A Btoujours une condition de course qui cp -Tn A Bn'a pas.
Stéphane Chazelas
6

Le -Tpeut fournir un échec si un répertoire n'existe pas correctement pour ce qui devrait être un fichier de destination:

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

Autrement dit, au lieu de réussir en cas de copie inattendue dans un sous-répertoire, un avertissement et un état de sortie non satisfaisant se produisent, ce qui pourrait entraîner l'arrêt du script et inspecter par l'homme pourquoi il existe un répertoire où il ne devrait pas être une.

branler
la source
0

L'utilisation d'un indicateur est également beaucoup plus claire et présente moins de risques d'effets indésirables lorsque la commande est utilisée dans un script au lieu d'être entrée manuellement. Corriger des points sur des chemins dans un script peut se traduire par toutes sortes de méfaits inattendus.

rackandboneman
la source