web-dev-qa-db-fra.com

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

Je me trompe toujours lorsque je dois utiliser cp ou mv: "ai-je besoin de -R option lorsque vous travaillez avec dir? "In GNU coreutils cp nécessite -R et mv non.

Je ne trouve aucune raison pour laquelle cp a besoin -R option pour copier les répertoires et mv pas. Je pense que cping dirs sans -R (mais se comportant récursivement comme il y a -R et comme mv le fait) ne causerait aucun problème, à part rompre les habitudes de quelqu'un en utilisant l'outil.

Connaissez-vous une explication? Peut-être avait-il une raison depuis longtemps?


Question supplémentaire: pourquoi les développeurs de coreutils ne font-ils pas cp copier les répertoires récursivement par défaut?

59
rslnx

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

Donc, c'est clair, changer le nom d'un fichier est facile: il suffit de changer le nom dans l'entrée du répertoire, rien d'autre. Cela permet de savoir si le fichier est en fait un fichier ou s'il s'agit d'un "fichier" utilisé pour stocker le contenu d'un autre répertoire. En effet, le même rename syscall fait les deux.

La copie, cependant, est une opération beaucoup moins triviale. Vous pourriez simplement copier le répertoire "fichier", mais vous auriez alors deux répertoires où les fichiers sont les mêmes (ce seraient des liens physiques). Si vous aviez un système qui autorise les liens physiques vers les répertoires, ce serait le cas, mais comme aucun système moderne ne permet cela, au moins pour les non-root, vous devez faire cette copie pour chaque sous-répertoire. Vous pouvez réellement demander à cp ce comportement avec cp -lR: -l pour lien dur, -R pour cette récursivité.

Mais laisser tout lié n'est probablement pas ce que vous voulez. À la place, vous souhaitez que cp copie 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 également de cette façon sur le disque. Il n'y a aucun moyen de copier un tas de fichiers, sinon de les parcourir individuellement et de les copier, et ce sont les types de systèmes de fichiers qui étaient utilisés lors de la conception des utilitaires de ligne de commande de base.

45
derobert

Permettez-moi de commencer par poser une autre question:

Quelle est la différence entre cp et cp -R?

Eh bien, sans le -R flag, il est uniquement possible de copier des fichiers, car il est assez inhabituel que quelqu'un veuille copier de manière non récursive un répertoire: une copie non récursive se traduirait simplement par un deuxième nom pour le répertoire, pointant directement vers la même structure de répertoire. Parce que c'est rarement ce que les gens veulent, et qu'il existe en fait un programme distinct qui fait cela (ln), une copie non récursive des répertoires n'est pas autorisée.

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

mv a b renomme simplement une seule entrée dans le répertoire, donc si un répertoire est mved, son contenu est automatiquement déplacé. En ce sens, mv fournit déjà la propriété récursive, c'est-à-dire le "renommage" de toutes les entrées du répertoire renommé, par ex. de a/1 à b/1. Un mv qui ne fait pas cela, c'est-à-dire qui renomme un répertoire a en b, mais conserve a/1 comme a/1, n'est pas ce que les gens comprennent lorsqu'ils se réfèrent à déplacer quelque chose: lorsque vous déplacez une armoire, le contenu de l'armoire est également déplacé. Cette autre opération, déplacer un répertoire sans son contenu, est également déjà disponible, elle s'appelle mkdir.

21
daniel kullmann

Habituellement, lorsque je suis en désordre avec la logique Unix, je regarde Plan9 pour voir comment les inventeurs Unix ont mis en œuvre les mêmes tâches des années plus tard sans se soucier de la compatibilité descendante.

Plan9 propose donc des outils cp et mv pour fonctionner 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, il y a dircp qui est vraiment @{cd fromdir && tar c .} | @{cd todir && tar xT} (syntaxe du 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 cp et mv pour les opérations de fichiers uniquement (pas les répertoires) apporte plus de clarté aux opérations sur disque et l'utilisation de tar pour copier les arborescences de fichiers est très confortable pour comprendre et scripting.

6
rslnx