web-dev-qa-db-fra.com

CP se comporte bizarre quand. (point) ou .. (point dot) sont le répertoire source

Cette réponse révèle que l'on peut copier tous les fichiers - y compris ceux cachés - à partir de répertoire src dans le répertoire dest comme:

mkdir dest
cp -r src/. dest

Il n'y a pas d'explication dans la réponse ou ses commentaires sur la raison pour laquelle cela fonctionne réellement, et personne ne semble trouver de la documentation à ce sujet non plus.

J'ai essayé quelques choses. Premièrement, le cas normal:

$ mkdir src src/src_dir dest && touch src/src_file src/.dotfile dest/dest_file
$ cp -r src dest
$ ls -A dest
dest_file  src

Ensuite, avec /. à la fin:

$ mkdir src src/src_dir dest && touch src/src_file src/.dotfile dest/dest_file
$ cp -r src/. dest
$ ls -A dest
dest_file  .dotfile  src_dir  src_file

Donc, cela se comporte similitant à *, mais copie également des fichiers cachés.

$ mkdir src src/src_dir dest && touch src/src_file src/.dotfile dest/dest_file
$ cp -r src/* dest
$ ls -A dest
dest_file  src_dir  src_file

. et .. sont des liens matériels appropriés comme expliqué ici , comme l'entrée de l'annuaire elle-même.

D'où vient ce comportement et où est-ce documenté?

18
iFreilicht

Le comportement est un résultat logique de l'algorithme documenté pour cp -R. Voir [~ # ~] posix [~ # ~ ~] , étape 2f:

Les fichiers du répertoire Source_file doivent être copiés dans le répertoire DEST_FILE , Prenant les quatre étapes (1 à 4) énumérés ici avec les fichiers comme Source_files .

. et .. sont des répertoires, respectivement le répertoire actuel et le répertoire parent. Ni sont spéciales aussi loin que la coquille ne sont concernées, donc non plus d'expansion, et le répertoire sera copié, y compris des fichiers cachés. *, D'autre part, sera étendu à une liste de fichiers, ce qui sera là où les fichiers cachés sont filtrés.

src/. est le répertoire actuel à l'intérieur src, qui est src lui-même; src/src_dir/.. est src_dir Le répertoire parent, qui est à nouveau src. Donc, de l'extérieur src, si src est un répertoire, spécifiant src/. ou src/src_dir/.. Comme le fichier source de cp sont équivalents et copiez le contenu de src, y compris des fichiers cachés.

Le point de spécifier src/. Est-ce que cela échouera si src n'est pas un répertoire (ou un lien symbolique à un répertoire), alors que src ne le ferais pas. Il copiera également le contenu de src uniquement, sans copier src lui-même; Cela correspond aussi à la documentation:

Si cible existe et nomme un répertoire existant, le nom du chemin de destination correspondant pour chaque fichier dans la hiérarchie de fichier doit être la concaténation de cible , un seul caractère SLASH si la cible ne s'est pas terminée dans une barre oblique, et le chemin du fichier relatif au répertoire contenant Source_file .

Donc cp -R src/. dest copie le contenu de src à dest/. (le fichier source est . dans src), alors que cp -R src dest copie le contenu de src à dest/src (le fichier source est src).

Une autre façon d'en penser est de comparer la copie src/src_dir et src/., plutôt que de comparer src/. et src. . se comporte comme src_dir dans le cas précédent.

29
Stephen Kitt

Quand vous courez cp -R src/foo dest, tu auras dest/foo. Donc si répertoire dest/foo n'existe pas, cp _ va le créer, puis copier le contenu de src/foo à dest/foo.

Quand vous courez cp -R src/. dest, cp voit que dest/. existe, puis c'est juste la question de copier le contenu de src/. à dest/..

Lorsque vous y pensez, copier un répertoire nommé . de src et fusionner son contenu avec le répertoire existant dest/., ça aura un sens.

1
telcoM