GNU/Linux >> Tutoriels Linux >  >> Linux

Est-ce que 'rm .*' supprime jamais le répertoire parent ?

L'expression .* est développé par bash pour inclure les répertoires actuel et parent :

$ ls -la
total 2600
drwxrwxrwx   2 terdon terdon 2162688 Sep 10 16:22 .
drwxr-xr-x 142 terdon terdon  491520 Sep 10 15:34 ..
-rw-r--r--   1 terdon terdon       0 Sep 10 16:22 foo
$ echo .*
. ..

Si j'exécute rm -rf .* sur ma Debian en utilisant GNU bash, version 4.2.36(1)-release et rm depuis rm (GNU coreutils) 8.13 , je reçois ce message :

$ rm -rf .*
rm: cannot remove directory: `.'
rm: cannot remove directory: `..'

Est-ce une chose GNU ou est-ce POSIX? Existe-t-il des systèmes * nix où la commande ci-dessus supprimera silencieusement . et .. ?

Aussi, est-ce une caractéristique de sécurité du shell ou du rm commande lui-même ?

Réponse acceptée :

La dernière version (en date de 2017) de la spécification POSIX pour le rm l'utilitaire est ici (et le précédent là) et interdit la suppression de . et .. .

Si l'un des fichiers point ou point-point est spécifié comme partie du nom de base d'un opérande (c'est-à-dire le composant du nom de chemin final) ou si un opérande se résout dans le répertoire racine, rm doit écrire un message de diagnostic sur l'erreur standard et ne rien faire plus avec de tels opérandes.

Comme l'a noté @jlliagre, la partie sur / est un ajout dans SUSv4.

La plus ancienne spécification Unix accessible au public que j'ai pu trouver (XPF4 CAE rev2 (1994)), spécifiait déjà que . et .. ne peut pas être supprimé, bien que les commentaires dans le journal des modifications de GNU fileutils suggèrent que c'était déjà le cas dans les anciennes spécifications POSIX.

Notez qu'il s'applique à dir/.. et ../ également, mais certaines implémentations (y compris celles certifiées UNIX comme Solaris 11 et macOS) ne protègent toujours pas contre rm -rf ../ ou rm -rf .*/ ).

historique

Les premiers unices

Le -r option pour rm a été ajouté dans Unix V3 (1973) bien qu'il ne supprimait que le contenu des répertoires, vous auriez toujours besoin d'utiliser rmdir pour supprimer des répertoires.

Cela a changé dans Unix V7 (1979, la version qui a également introduit le shell Bourne et dont dérivent la plupart des Unix). rm -r supprime désormais également les répertoires et ne supprime pas le .. arborescence de répertoires. La page de manuel indique :

Il est interdit de supprimer le fichier .. simplement pour éviter les conséquences antisociales de faire par inadvertance quelque chose comme rm -r .* .

(bien que l'on puisse dire que rm -r .* est toujours antisocial car il supprime tout car . est inclus).

Il a quand même accepté de supprimer . bien que cela ne dissocie pas le . ou .. entrées. Alors, rm -r . était un moyen efficace de vider le répertoire courant.

Notez également que la sauvegarde ne concernait qu'un .. littéral argument, pas pour dir/.. ou ./.. . Donc, rm -rf ./.* supprimerait toujours tout dans le répertoire parent de manière récursive.

Il est intéressant de voir que c'était déjà pour contourner le bogue/mauvaise fonctionnalité par laquelle les globs pouvaient inclure . et .. dans leur expansion. Cela a été corrigé dans le shell Forsyth (la base du shell Minix original et de pdksh) à la fin des années 80, zsh (1990) et fish (2005) mais pas les autres shells et en particulier pas le POSIX sh langage qui nécessite l'expansion de .* pour inclure . et .. s'ils sont renvoyés par readdir() (bash résout le problème en partie uniquement avec shopt -s dotglob où globs (sauf le .xxx ceux) n'incluent pas . ou .. , et avec ksh , vous pouvez le corriger en faisant FIGNORE='@(.|..)' ).

Connexe :Comment supprimer un fichier utilisé par un autre processus ?

Quand exactement interdire . ainsi a été ajouté n'est pas toujours clair et varie avec chaque Unix. Quelques découvertes ci-dessous.

BSD

L'interdiction de . a été ajouté entre 2.9BSD (1983) et 2.10BSD (1987) et entre 4.2BSD (1983) et 4.3BSD (1986) (voir ce changement horodaté 1985 dans le unix-history-repo).

$ wget -qO- http://www.tuhs.org/Archive/PDP-11/Distributions/ucb/2.9BSD/root.tar.gz |
    zgrep -ao 'rm: canno[[:print:]]*'
rm: cannot remove `..'
$ wget -qO- http://www.tuhs.org/Archive/PDP-11/Distributions/ucb/2.10bsd.tar.gz |
    zgrep -ao 'rm: canno[[:print:]]*'
rm: cannot remove `.' or `..'
rm: cannot remove `.' or `..'n");

Pour dir/. et dir/.. , voir ce changement en 1988 (BSD 4.3 Net/1).

A ce jour, le rm de FreeBSD (et ses dérivés comme macOS) vide toujours le répertoire courant ou parent sur rm -rf ./ ou rm -rf ../ cependant (importe pour rm -rf .*/ ).

Système V

Je n'ai pas beaucoup d'informations car ni la source ni le binaire ne sont accessibles au public pour les dérivés AT&T Unix après la V7. Dans son manuel en ligne, HPUX (basé sur System III) mentionne encore qu'il n'interdit que .. alors qu'en fait, il interdit les deux, ce qui indique qu'au moins SysIII n'a probablement pas interdit la suppression de . (modifier :En regardant maintenant le SysIII rm code source, il est pratiquement inchangé depuis Unix V7).

Tous les autres manuels en ligne que j'ai consultés mentionnent la suppression de . ou .. est interdit, ce qui devrait être conforme à POSIX.

Solaris rm vide toujours le répertoire courant ou parent sur rm -rf ./ ou rm -rf ../ .

GNU

Le premier journal des modifications pour les fileutils GNU contient toutes les informations historiques.

Alors qu'à l'origine ni la suppression de . ou .. étaient interdits, .. a été interdit en premier, puis les deux (y compris dir/. ), le tout entre 1990 et 1991.

autre

Comme nous l'avons vu, en zsh , le développement de .* (ou n'importe quel glob) n'inclut jamais . ou .. (même en sh mode d'émulation). Le rm builtin (que vous obtenez si vous zmodload zsh/files ) ne traite donc pas . ou .. spécialement. Donc, avec ce zsh intégré, vous pouvez rm -rf . ou rm -rf .. pour vider . ou .. , mais rm -rf .* ne supprimera pas . ou .. .

Dans la boîte occupée rm , l'interdiction de suppression de . et .. a été ajouté en 0.52 (2001)


Linux
  1. Comment installer R 3.3.1 dans le propre répertoire ?

  2. Rsync modifie les autorisations du répertoire ?

  3. Comment compter le nombre de fichiers dans un répertoire et supprimer les plus anciens si le nombre dépasse 5 ?

  4. Que produit pwd ?

  5. Quel est le moyen le plus rapide de supprimer tous les fichiers et sous-dossiers d'un répertoire ?

Comment supprimer (supprimer) un fichier ou un répertoire sous Linux

Comment supprimer un répertoire sous Linux

Comment supprimer (supprimer) le répertoire sous Linux

Supprimer le répertoire sous Linux - Comment supprimer un dossier de la ligne de commande

Comment supprimer des domaines/sous-domaines dans le cPanel ?

Comment ajouter le sous-répertoire bin du premier répertoire de GOPATH à PATH ?