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 rm
ou rmdir 'this_is_link/'
, la même erreur Not a directory
se 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?
Réponses:
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;basename
etdirname
ignorer 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.la source
Ma prise:
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é.
la source
rm
appelle stat (enfin, newfstatat, en fait, avec l'AT_SYMLINK_NOFOLLOW
option) et refuse de poursuivre, alors que rmdir appelle réellement rmdir (2), mais obtientENOTDIR
.AT_SYMLINK_NOFOLLOW
l'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.stat
etstat -L
ne diffère que si l'argument est donné sans barre oblique de fin.rm
se comporte correctement etrmdir
ne 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 .