cp --no-target-directory expliqué

10

Question: J'ai besoin d'un exemple simple d'utilisation cp --no-target-directory.

J'ai des difficultés à comprendre cp --no-target-directory. Je comprends l'explication pourmv --no-target-directory , mais je ne peux pas vraiment imaginer une façon de l'utiliser cp.

Par exemple, lorsque la commande mv /tmp/source /tmp/destréussit, rien ne garantit qu'il a /tmp/sourceété renommé /tmp/dest: il aurait pu être renommé à la /tmp/dest/sourceplace, si un autre processus avait été créé en /tmp/desttant que répertoire. Cependant, en cas de mv -T /tmp/source /tmp/destsuccès, il ne fait aucun doute que /tmp/source was renamed to/ tmp / dest`. ( source )

erch
la source

Réponses:

15

Par défaut, cpteste si son dernier argument est un répertoire existant. Si cela se produit, cpcrée un lien dans ce répertoire, avec le nom de base de la source. Autrement dit, étant donné la commande

cp foo/bar wibble

s'il wibbles'agit d'un répertoire existant, cpcopie la source dans wibble/bar. Si wibblen'existe pas, cplie la source à wibble.

Si vous voulez être sûr que la copie est toujours wibble, vous pouvez spécifier l' option --no-target-directory(alias -T). De cette façon, en cas de cpsuccès, vous pouvez être sûr que la copie est appelée wibble. S'il wibbleexistait déjà en tant que répertoire, il cpéchouera.

Sous forme de tableau:

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

La seule différence est qu'avec -T, dans le cas où la cible est un répertoire existant, la commande renvoie une erreur. Ceci est utile lorsque vous vous attendez à ce que le répertoire n'existe pas: vous obtenez un message d'erreur au lieu de quelque chose d'imprévu.

Il en va de même pour mvet ln. Si la cible est un répertoire existant, avec -T, ils signalent une erreur plutôt que de faire silencieusement quelque chose de différent.

Avec cp, il y a un cas différent. Si vous effectuez une copie récursive et que la source est un répertoire, copiez cp -Tle contenu de la source dans la destination, plutôt que de copier la source elle-même. Autrement dit, étant donné

$ tree source destination 
source
└── foo
destination
└── bar

puis

$ cp -rv source destination
`source' -> `destination/source'
`source/foo' -> `destination/source/foo'

tandis que

% cp -rvT source destination
`source/foo' -> `destination/foo'
Gilles 'SO- arrête d'être méchant'
la source
8

Vous utiliseriez --no-target-directorysi vous ne voulez pas qu'un répertoire source soit copié sous un répertoire de destination existant, vous voulez que le répertoire source soit copié dans le répertoire de destination.

Voici un exemple de copie de répertoire avec et sans --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

Vous pouvez obtenir quelque chose du même effet en suffixant le (s) nom (s) du répertoire source avec une barre oblique /.comme dans: cp -r a/. bqui copie le répertoire source a sur b et non en dessous b .

Aucune des méthodes ci-dessus ne revient à dire "copier uniquement le contenu du répertoire source vers la destination existante" car, si vous demandez de conserver le temps et les autorisations, le répertoire de destination existant acquiert l'heure et les autorisations du répertoire source. Un exemple (modifié pour supprimer les informations inutiles):

$ 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

Une copie de contenu uniquement ne transfère pas le mode ou les horodatages du répertoire source vers le répertoire de destination.

Ian D. Allen
la source
2

Et les choses suivantes?

$ 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’

En tant que tel, c'est juste une façon différente d'écrire cp Dir_1/* Dir_2/. Cependant, il attrape des fichiers cachés à la racine de Dir_1 qui seraient manqués par un simple 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’
Railgun2
la source
fonctionne pour moi avec l' --no-target-directoryoption [out] : tant que j'utilise --recursive, tout va bien [avec coreutils 8.12sous GNU / Linux]. La principale différence semble être qu'avec --no-target-directoryle contenu mais pas le répertoire lui-même est copié [recherche toujours en cours]
erch