Pourquoi `cp` et` rm` traitent-ils les répertoires séparément?


10

Pourquoi les outils aiment-ils cpet rmtraitent-ils les répertoires séparément des fichiers normaux? Ils exigent tous deux que l'utilisateur spécifie explicitement qu'elle souhaite un comportement récursif, sinon ils ne traiteront pas du tout des répertoires.

Ma première interaction (il y a quelque temps) avec les ordinateurs était sur un environnement Windows / GUI / pointer-cliquer / glisser-déposer, il semblait toujours naturel que ces opérations se comportent de la même manière, quelle que soit la cible.

Ce comportement me frustre particulièrement lorsque je donne des commandes avec des caractères génériques. Que faire si je veux supprimer tout dans un répertoire ( *) à l'exception des sous-répertoires non vides ?

Je peux seulement imaginer qu'il s'agit d'une sorte de fonctionnalité de sécurité pour empêcher l'utilisateur de se tirer une balle dans le pied, mais cela contredit ma compréhension de quelques principes Unix:

  • Unix ne protège généralement pas l'utilisateur d'elle-même. Il a toujours supposé que l'utilisateur savait ce qu'elle faisait.
  • Pour Unix, tout est un fichier. Un répertoire n'est-il pas simplement un autre fichier? Pourquoi sont-ils traités différemment?

Mes questions:

  • Ce comportement découle-t-il d'une limitation technique ou s'agit-il d'un choix délibéré?

Et dans le cas de ce dernier,

  • existe-t-il des récits historiques des raisons qui ont motivé ce choix?

Pour rmau moins, si vous voulez ignorer la différence entre les fichiers et les répertoires, vous pouvez mettre dans votre ~/.bashrcfichier: alias rm='rm -r'.
BenjiWiebe

1
Voir aussi la question différente mais connexe unix.stackexchange.com/questions/46066/…
derobert

1
Vous ne pouvez pas comparer cp et rm avec le gestionnaire de fichiers Windows. Démarrez cmd.exe et essayez de copier et supprimer et de comparer le comportement.
ott--

Réponses:


11

Pourquoi le programme Unix mv de Derobert n'a pas besoin de l'option -R (récursive) pour les répertoires mais cp en a besoin? répond essentiellement à votre question: copier ou supprimer un fichier normal est différent de faire la même opération avec un répertoire, car pour un répertoire, vous devez traiter tous les fichiers qu'il contient. L'opération est donc fondamentalement différente.

Il convient également de noter qu'il existe un utilitaire spécial rmdirqui ne peut agir que sur des répertoires vides. Sans vérifier les faits, cela conduit à conclure que peut-être à l'origine, il rmn'était possible de supprimer que les non-répertoires et que la suppression en profondeur devait être réalisée en utilisant récursivement rmdes répertoires vides puis rmdirsupprimés.


rmdirest également le nom de l'appel système utilisé pour supprimer un répertoire. Le répertoire doit être vide pour l'appel système et l'utilitaire du même nom est simplement "frontal", similaire à la unlinkcommande et à l'utilitaire.
jordanm

Exactement - c'est ce qui m'amène à penser qu'initialement, rmil aurait été impossible de supprimer les répertoires (car les utilitaires de ligne de commande ne sont souvent que des wrappers relativement simples autour des appels système).
peterph

Le titre de ma question pourrait induire en erreur en pensant que je pose des questions sur les détails techniques. Je demandais si c'était un choix délibéré. Je me demande si je suis le seul à penser que du point de vue de l'utilisateur final, ce comportement est incohérent. J'accepte votre réponse car elle répond indirectement à ma question: les limitations techniques des internes Unix (au niveau d'un appel système) semblent être à l'origine de ce comportement, et l'héritage nous empêche probablement de le faire autrement aujourd'hui. Les "enveloppements simples autour des appels système" ne sont-ils pas censés nous donner des comportements plus intelligents?
rahmu

2
Du point de vue de l'utilisateur final, cela semble vraiment étrange, mais vous demandiez en fait les raisons. :) En ce qui concerne les emballages - tout dépend de leur "simplicité" (et de ce que vous voulez toujours appeler "simple"). Modern rmn'est certainement pas seulement un simple wrapper (il est capable de supprimer les fichiers mroe à la fois et les répertoires également). Si vous n'aimez pas lui donner l' -roption, utilisez la fonctionnalité d'alias de votre shell ou créez votre propre wrapper qui le mettra en place (ce qui serait plus lent, mais indépendant du shell que vous utilisez).
peterph

2

Dans certaines versions UNIX, la page de manuel de rm le spécifie comme une commande pour dissocier un fichier.
Sous UNIX, les fichiers sont des objets du système de fichiers appelés Inodes, sans nom ni emplacement autre qu'un ID dans le système de fichiers. Leurs noms leur font référence dans divers répertoires, qui sont un type de fichier qui indexe les fichiers (ou répertoires, car ce sont des fichiers) qui y sont répertoriés.
Lors de la dissociation d'un fichier, le nombre de références du fichier diminue et lorsqu'il atteint 0, il est en fait supprimé, car il est marqué comme libre par le système de fichiers et ses blocs / extensions sont également marqués comme libres.

Si vous aviez la possibilité de rm un répertoire sans dissocier d'abord les fichiers qu'il contient, vous atteindrez un point où vous avez des inodes référencés dans votre système de fichiers mais auxquels vous ne pouvez pas accéder par tout moyen normal.
Puisqu'il y a une référence à eux en fonction de leur nombre de références, ils ne sont pas marqués comme supprimés et deviennent des fichiers perdus.
Cela devient encore plus complexe lorsque les "fichiers" perdus sont des répertoires et, en tant que tels, augmente la quantité potentielle de stockage perdu dans le système de fichiers.

Donc, rm -r a été ajouté, pour faciliter la vie des utilisateurs UNIX, au détriment de "l'esprit UNIX" standard, car il est plus complexe que les utilitaires UNIX classiques car il descend dans les répertoires et supprime les fichiers à l'intérieur,

De plus, au début d'UNIX, les systèmes ne disposaient pas de beaucoup de mémoire, et le mappage de la structure récursive d'un répertoire avait une baisse de performances, et il était parfois impossible de le faire sans fractionner le travail.

cp, lit un fichier et le copie, bloc par bloc. S'il copiait un répertoire de la même manière qu'un fichier, il ajouterait des références aux fichiers à l'intérieur sans augmenter leur nombre de références, ce qui pourrait conduire à des données incohérentes (si lecture / écriture dans un inode qui est marqué comme libre depuis leur l'inode d'origine a été supprimé), des données perdues - car la suppression de la dernière référence (connue) à un fichier pourrait entraîner le recyclage de son numéro d'inode.

Pour la foule tl; dr: les
répertoires sous UNIX sont un type de fichier, c'est vrai, mais comme les informations qu'ils contiennent sont traitées différemment par le système, car ce sont des métadonnées du système de fichiers, les commandes qui manipulent les fichiers ne peuvent pas fonctionner sur des répertoires sans changement de comportement pour manipuler également les métadonnées dépendantes.

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.