Barres obliques sur les liens symboliques vers les répertoires

8

J'essaie d'émuler le processus de résolution de chemin (voir la page de manuel path_resolution) dans les systèmes de type Unix.

Mon OS est Linux avec GNU coreutils 8.7.

Afin de clarifier la signification de «/» de fin supplémentaire dans la résolution, j'ai fait les choses suivantes dans un shell:

mkdir this_is_dir
ln -s this_is_dir this_is_link
rm this_is_link

Tout allait bien, car this_is_link est un lien symbolique, et je viens de le supprimer. Mais en essayant:

mkdir this_is_dir
ln -s this_is_dir this_is_link
rm this_is_link/

Cela a fait écho rm: cannot remove 'this_is_link/': Is a directory

Eh bien, je pensais que le '/' de fin provoquait le suivi du lien symbolique. J'ai donc essayé une autre commande:rmdir this_is_link/

Et un résultat amusant est sorti: rmdir: failed to remove 'this_is_link/': Not a directory

Pas ce à quoi je m'attendais. J'ai donc demandé à mon ami de confirmer si le même résultat pouvait être obtenu sur son système. Il avait une version de coreutils inférieure à la mienne. Et le résultat était incroyable, peu importe rmou rmdir 'this_is_link/', la même erreur Not a directoryse produit .

Et un autre ami vient de l'essayer sur son Mac OS, le résultat est: rm=> 'Est un répertoire', rmdir=> le répertoire est supprimé avec succès, le lien est resté .

Existe-t-il des spécifications sur le comportement exact de la résolution du chemin?

ymfoi
la source

Réponses:

7

La spécification POSIX / Single Unix spécifie qu'un nom de chemin avec une barre oblique de fin doit faire référence à un répertoire (voir définitions de base §4.11 résolution de nom de chemin ). foo/est en fait défini comme équivalent à foo/.(à des fins de résolution de chemin, pas lors de la manipulation des noms de fichiers; basenameet dirnameignorer les barres obliques de fin). La plupart des implémentations respectent cela, mais il y a quelques exceptions.

Cela explique le comportement de rm this_is_link/: c'est équivalent à rm this_is_link/., où l'argument est clairement un répertoire.

rmdir this_is_link/devrait également se référer au répertoire. Ce n'est pas le cas sur votre machine est un bug dans GNU coreutils. OSX se comporte correctement ici.

Gilles 'SO- arrête d'être méchant'
la source
C'est exactement ce dont j'avais besoin, merci mec!
ymfoi
-1

Ma prise:

  • '' rm link / '' échoue parce que rm regarde le dernier caractère, voit que c'est une barre oblique, donne le diagnostic (pas vraiment correct) que vous avez vu;
  • '' rmdir link / '' échoue bien: le lien n'est pas un répertoire, c'est un lien symbolique
  • '' rm link '' réussira correctement

Soit dit en passant, la résolution de chemin n'a pas grand-chose à voir avec cela, il semble simplement que "rm" coupe un coin plutôt que d'invoquer (correctement) "stat" sur un argument (ce que fait rmdir).

À votre santé.

Forme de vie extraterrestre
la source
1
En fait, l'inverse semble être vrai: rmappelle stat (enfin, newfstatat, en fait, avec l' AT_SYMLINK_NOFOLLOWoption) et refuse de poursuivre, alors que rmdir appelle réellement rmdir (2), mais obtient ENOTDIR.
Ansgar Esztermann
@AnsgarEsztermann AT_SYMLINK_NOFOLLOWl'empêchera de suivre le lien symbolique, donc rm devrait supprimer le lien lui-même au lieu d'imprimer "Pas un répertoire" qui ne correspond pas à la circonstance.
ymfoi
À partir d'une brève vérification avec stat (1), la barre oblique de fin remplacera l'option. La sortie de statet stat -Lne diffère que si l'argument est donné sans barre oblique de fin.
Ansgar Esztermann
@AnsgarEsztermann Oh, je vois ... Thx. Qu'en est-il des différents effets sur différents environnements? Des idées?
ymfoi
1
C'est le contraire: sur la machine de ymfoi, rmse comporte correctement et rmdirne l'est pas. La fin /devrait les forcer à traiter leur argument comme un répertoire, selon la norme POSIX. Voir ma réponse pour les références .
Gilles 'SO- arrête d'être méchant'