Pourquoi un programme mv n'a pas besoin de l'option -R (récursive) pour les répertoires mais cp en a besoin?


58

Je me fais toujours avoir quand il faut utiliser cpou mv: "ai-je besoin d'une -Roption lorsque je travaille avec dir?" Dans GNU, coreutils a cpbesoin -Ret mvn’a pas.

Je ne peux pas trouver aucune raison pour laquelle cpbesoin de l' -Roption pour copier les répertoires et mvn'en a pas. Je pense cpqu'ingérer des répertoires sans -R(mais se comporter de manière récursive comme il y en a -Ret comme le mvferait) ne poserait aucun problème si ce n'est de casser les habitudes de quelqu'un en utilisant l'outil.

Connaissez-vous une explication? Peut-être qu'il y avait une raison il y a longtemps?


Question supplémentaire: pourquoi les développeurs de coreutils ne font-ils pas les répertoires de cpcopie de manière récursive par défaut?

Réponses:


45

Un répertoire est (conceptuellement) un "fichier" spécial contenant une liste de noms et les numéros d'inode vers lesquels ces noms pointent. Certains noms peuvent être des sous-répertoires. Il existe une entrée spéciale ..qui pointe vers le répertoire parent.

Il est donc facile de changer le nom d'un fichier: il suffit de changer le nom dans l'entrée du répertoire, rien d'autre. Ceci est valable si le fichier est en réalité un fichier ou un "fichier" utilisé pour stocker le contenu d'un autre répertoire. En effet, le même renameappel système fait les deux.

La copie est cependant une opération beaucoup moins triviale. Vous pouvez simplement copier le répertoire "fichier", mais vous disposerez alors de deux répertoires dans lesquels les fichiers sont identiques (ce sont des liens physiques). Si vous aviez un système qui autorise les liens physiques vers des répertoires, ce serait le cas, mais comme aucun système moderne ne permet cela, du moins pour les lecteurs non root, vous devez faire cette copie pour chaque sous-répertoire. Vous pouvez réellement demander cpce problème avec cp -lR: -lfor link, -Rpour cette récursion.

Mais laisser tout lié n'est probablement pas ce que vous voulez. Au lieu de cela, vous voulez cpcopier chaque fichier. C'est une opération assez coûteuse: chaque fichier doit être lu en mémoire et réécrit sur le disque dans un deuxième emplacement. Il faut en fait plusieurs appels système pour ouvrir, lire, écrire et fermer les fichiers, et cela doit être répété pour chaque fichier.

Les systèmes de fichiers traditionnels fonctionnent de la même manière sur le disque. Il n’existe aucun moyen de copier un groupe de fichiers, sauf de les parcourir individuellement et de les copier, et il s’agit des types de systèmes de fichiers utilisés lors de la conception des utilitaires de base en ligne de commande.


Le passage mvd’un système de fichiers à un autre est-il identique "changez simplement le nom dans l’entrée du répertoire"?
rslnx

5
Non, le système de fichiers croisé est identique à une copie + suppression (en effet, l' renameappel système échouera pour le système de fichiers croisé). Pas sûr si, historiquement, mvmême pris en charge les déplacements cross-fs.
derobert

9
Je peux vous dire, d’expérience directe et non de spéculation, que Classic mvn’appuyait pas les mouvements croisés. Auparavant, il essayait simplement d' rename()imprimer un message d'erreur s'il échouait. Je me souviens encore du sentiment choqué que j'avais eu la première fois que j'avais utilisé cette nouvelle fonctionnalité par accident. Pourquoi est-ce que ça prend si longtemps? Oh, c'est une copie récursive que je n'avais pas l'intention de faire!
Alan Curry

5
@RuslanKhusnullin Les options de ligne de commande des commandes courantes sont très difficiles à modifier, en raison de leur utilisation dans les scripts shell. Quelqu'un peut être dépendant du comportement actuel de cp de refus de copie. Le contenu de cross-fs a probablement été jugé moins susceptible de provoquer une casse, bien que, comme vous pouvez le constater, Alan ait encore été surpris.
derobert

1
@derobert, ça n'a pas marché (le système de fichiers croisé mvne fonctionnait que pour des fichiers individuels sous BSD 4.2 sous VAX).
vonbrand

21

Permettez-moi de commencer par poser une autre question:

Et quelle est la différence entre cpet cp -R?

Eh bien, sans l' -Rindicateur, il est uniquement possible de copier des fichiers, car il est plutôt inhabituel que quelqu'un veuille copier un répertoire de manière non récursive: une copie non récursive donnerait simplement un deuxième nom au répertoire, pointant directement vers le même répertoire. structure. Parce que c'est rarement ce que les gens veulent, et qu'il existe en fait un programme distinct qui fait this ( ln), une copie non récursive de répertoires n'est pas autorisée.

Quelle pourrait alors être la différence entre mvet mv -R?

mv a bil ne fait que renommer une seule entrée dans le répertoire. Ainsi, si un répertoire est mvédité, son contenu est automatiquement déplacé. En ce sens, mvfournit déjà la propriété récursive, c’est-à-dire le "renommage" de toutes les entrées du répertoire renommé, par exemple de a/1à b/1. A mvne pas faire, à savoir qui renomme un répertoire aà b, mais garde a/1aussi a/1, est ce que les gens comprennent quand ils se réfèrent à déplacer quelque chose: Lorsque vous déplacez une armoire, le contenu de l'armoire sont déplacés. Cette autre opération, déplacer un répertoire sans son contenu, est également déjà disponible, elle est appelée mkdir.


2
C'est vrai, je pensais juste cpet mvcomme opérations qu'ils s'appellent: «faire une copie» et «bouger». Donc, si je veux faire une copie d'une tasse de café, je m'attendrais à avoir une autre tasse de café avec le même remplissage (boisson au café). Le problème est que les outils ne sont pas destinés aux «gens ordinaires» mais aux nerds qui connaissent la structure du disque et du système de fichiers, pas aux entités virtuelles telles que les fichiers et les répertoires de fichiers.
Rslnx

1
Réponse bien structurée et raisonnée.
Spedge

1
@RuslanKhusnullin Votre analogie avec le café fonctionne pour cpet mvaussi - elle ne nécessite aucun niveau de "nerdness" pour comprendre, juste du sens commun fondamental. Une copie conforme d'une tasse de café n'est pas une tasse vide - vous devez également copier récursivement non seulement la tasse, mais tout son contenu (le café). Toutefois, lorsque vous déplacez une tasse de café, vous ne devez pas déplacer le contenu séparément: le contenu se déplace naturellement avec le récipient.
Jw013

1
@ jw013 Vous m'avez impressionné avec "quand vous déplacez une tasse de café, vous ne devez pas déplacer le contenu séparément", c'est vraiment logique, merci. Mais c'est une autre couche d'abstraction. Je pense que vous voulez dire "traiter un fichier comme un inode" pendant que je pense à des fichiers comme des séquences d'octets sans méta-information.
rslnx

6

Habituellement, lorsque je suis bousillé avec la logique Unix, je regarde Plan9 pour voir comment les inventeurs Unix ont implémenté les mêmes tâches des années plus tard sans bloquer la compatibilité ascendante.

Donc, les offres cpet les mvoutils de Plan9 fonctionnent uniquement avec des fichiers.

`cp f1 f2` creates f2 and copies f1's contents into it.
`mv f1 f2` renames f1 to f2 if f1 and f2 are in the same dir
           does `cp f1 f2 && rm f1` else
           can rename dirs (`mv d1 d2`) but will not move dir to another dir.

Pour copier un répertoire, dircpc’est vraiment @{cd fromdir && tar c .} | @{cd todir && tar xT}(syntaxe de shell rc)

Pour déplacer un dir, je pense qu'il n'y a que dircp d1 d2 && rm -r d1

Je pense que cette décision de limiter cpet de limiter mvles opérations sur les fichiers (et non les répertoires) apporte plus de clarté aux opérations de disque et que l’utilisation tarde la copie des arborescences de fichiers est très confortable pour la compréhension et l’écriture de scripts.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.