Très probablement parce que la suppression du répertoire de travail actuel ne serait pas une bonne idée.
Alexej Magura
D' accord - Je aime le comportement par défaut, mais il est pas compatible avec, par exemple, find . -print.
mbroshi
@AlexejMagura bien que je sympathise, je ne vois pas pourquoi la suppression du répertoire actuel devrait être différente de la suppression d'un fichier ouvert. L'objet restera en vie jusqu'à ce qu'il y ait une référence, puis les ordures seront collectées par la suite. Vous pouvez faire cd ..; rm -r diravec un autre shell avec une sémantique assez claire ...
Rmano
@Rmano c'est vrai: c'est juste quelque chose que je ne ferais pas par principe: il suffit de monter un répertoire puis de supprimer le répertoire courant. Je ne sais pas vraiment pourquoi c'est si important - bien que j'ai eu des malheurs avec le répertoire actuel qui n'existe plus, tels que les chemins relatifs ne fonctionnent plus, mais vous pouvez toujours sortir en utilisant un chemin absolu - mais une partie de moi dit simplement que ce n'est pas une bonne idée en général.
Alexej Magura
Réponses:
29
Les membres en sont findutilsconscients , c'est pour compatible avec * BSD:
L'une des raisons pour lesquelles nous ignorons la suppression de "." est pour la compatibilité avec * BSD, où cette action a commencé.
Les NOUVELLES du code source de findutils montrent qu'ils ont décidé de conserver le comportement:
#20802: If -delete fails, find's exit status will now be non-zero. However, find still skips trying to delete ".".
[MISE À JOUR]
Étant donné que cette question est devenue l'un des sujets d'actualité, je plonge dans le code source de FreeBSD et j'en viens à une raison plus convaincante.
Chaque répertoire contient toujours des entrées pour lui-même, appelées ".", Et son parent, ".."; ceux-ci doivent être ignorés, sinon le programme sera en boucle pour toujours .
"boucle pour toujours" , c'est la même chose que la façon de le renamedécrire comme "chemins de système de fichiers cycliques" ci-dessus.
Je modifie légèrement le code et pour le faire fonctionner sous Kali Linux basé sur cette réponse :
Parce que votre findcommande retourne .comme résultat. Depuis la page info de rm:
Toute tentative de suppression d'un fichier dont le dernier composant du nom de fichier est '.' ou '..' est rejeté sans aucune invite, comme mandaté par POSIX.
Ainsi, il semble que findles règles POSIX restent dans ce cas.
Comme il se doit: POSIX est roi, plus la suppression du répertoire actuel pourrait causer de très gros problèmes en fonction de l'application parente et non. Comme si le répertoire actuel était /var/loget que vous l'avez exécuté en tant que root, pensant qu'il supprimerait tous les sous-répertoires et qu'il supprimait également le répertoire actuel?
Alexej Magura
1
C'est une bonne théorie, mais la manpage pour finddit: "Si la suppression a échoué, un message d'erreur est émis." Pourquoi aucune erreur n'est-elle imprimée?
mbroshi
1
@AlexejMagura Suppression du répertoire courant fonctionne très bien en général: mkdir foo && cd foo && rmdir $(pwd). C'est la suppression .(ou ..) qui ne fonctionne pas.
La signification de la suppression du nom de chemin / point n'est pas claire, car le nom du fichier (répertoire) dans le répertoire parent à supprimer n'est pas clair, en particulier en présence de plusieurs liens vers un répertoire.
Alors que 林果 皞 et Thomas ont déjà donné de bonnes réponses à ce sujet, je pense que leurs réponses ont oublié d'expliquer pourquoi ce comportement a été mis en œuvre en premier lieu.
Dans votre find . -deleteexemple, la suppression du répertoire actuel semble assez logique et sensée. Mais considérez:
$ find . -name marti\*
./martin
./martin.jpg
[..]
Supprime . semble- toujours logique et sensée?
La suppression d'un répertoire non vide est une erreur - il est donc peu probable que vous perdiez des données avec cela avec find(bien que vous puissiez le faire avec rm -r) - mais votre shell aura son répertoire de travail actuel défini dans un répertoire qui n'existe plus, ce qui peut prêter à confusion et un comportement surprenant:
$ pwd
/home/martin/test
$ rm -r ../test
$ touch foo
touch: cannot touch 'foo': No such file or directory
Ne pas supprimer le répertoire actuel est tout simplement une bonne conception d'interface et est conforme au principe de la moindre surprise.
find . -print
.cd ..; rm -r dir
avec un autre shell avec une sémantique assez claire ...Réponses:
Les membres en sont
findutils
conscients , c'est pour compatible avec * BSD:Les NOUVELLES du code source de findutils montrent qu'ils ont décidé de conserver le comportement:
[MISE À JOUR]
Étant donné que cette question est devenue l'un des sujets d'actualité, je plonge dans le code source de FreeBSD et j'en viens à une raison plus convaincante.
Voyons le code source de l'utilitaire de recherche de FreeBSD :
Comme vous pouvez le voir, s'il ne filtre pas les points et les points, il atteindra la
rmdir()
fonction C définie par POSIXunistd.h
.Faites un test simple, rmdir avec l'argument point / point-point retournera -1:
Voyons comment POSIX décrit rmdir :
Aucune raison n'a été donnée pourquoi
shall fail
.J'ai trouvé
rename
expliquer quelque raison n:Chemins cycliques du système de fichiers ?
Je regarde le langage de programmation C (2e édition) et recherche un sujet de répertoire, étonnamment j'ai trouvé que le code est similaire :
Et le commentaire!
"boucle pour toujours" , c'est la même chose que la façon de le
rename
décrire comme "chemins de système de fichiers cycliques" ci-dessus.Je modifie légèrement le code et pour le faire fonctionner sous Kali Linux basé sur cette réponse :
Voyons voir:
Cela fonctionne correctement, maintenant que se passe-t-il si je commente l'
continue
instruction:Comme vous pouvez le voir, je dois utiliser Ctrl+ Cpour tuer ce programme en boucle infinie.
Le répertoire '..' lit sa première entrée '..' et boucle pour toujours.
Conclusion:
GNU
findutils
essaie d'être compatible avec l'find
utilitaire dans * BSD .find
l'utilitaire dans * BSD utilise en interne larmdir
fonction C conforme POSIX que le point / point-point n'est pas autorisé.La raison de l'
rmdir
interdiction de point / point-point est d'empêcher les chemins cycliques du système de fichiers.Le langage de programmation C écrit par K&R montre l'exemple de la façon dont point / point-point mènera au programme de boucle pour toujours.
la source
Parce que votre
find
commande retourne.
comme résultat. Depuis la page info derm
:Ainsi, il semble que
find
les règles POSIX restent dans ce cas.la source
/var/log
et que vous l'avez exécuté en tant que root, pensant qu'il supprimerait tous les sous-répertoires et qu'il supprimait également le répertoire actuel?man
page pourfind
dit: "Si la suppression a échoué, un message d'erreur est émis." Pourquoi aucune erreur n'est-elle imprimée?mkdir foo && cd foo && rmdir $(pwd)
. C'est la suppression.
(ou..
) qui ne fonctionne pas.L'appel système rmdir échoue avec EINVAL si le dernier composant de son chemin d'argument est
"."
. Il est documenté à http://pubs.opengroup.org/onlinepubs/009695399/functions/rmdir.html et la justification de ce comportement est:la source
Appel
rmdir(".")
tant système n'a pas fonctionné lorsque je l'ai essayé, donc aucun outil de niveau supérieur ne peut réussir.Vous devez supprimer le répertoire par son vrai nom et non par son
.
alias.la source
Alors que 林果 皞 et Thomas ont déjà donné de bonnes réponses à ce sujet, je pense que leurs réponses ont oublié d'expliquer pourquoi ce comportement a été mis en œuvre en premier lieu.
Dans votre
find . -delete
exemple, la suppression du répertoire actuel semble assez logique et sensée. Mais considérez:Supprime
.
semble- toujours logique et sensée?La suppression d'un répertoire non vide est une erreur - il est donc peu probable que vous perdiez des données avec cela avec
find
(bien que vous puissiez le faire avecrm -r
) - mais votre shell aura son répertoire de travail actuel défini dans un répertoire qui n'existe plus, ce qui peut prêter à confusion et un comportement surprenant:Ne pas supprimer le répertoire actuel est tout simplement une bonne conception d'interface et est conforme au principe de la moindre surprise.
la source