Barras finales en enlaces simbólicos a directorios

8

Estoy tratando de emular el proceso de resolución de ruta (consulte la página de manual path_resolution) en sistemas similares a Unix.

Mi sistema operativo es Linux con GNU coreutils 8.7.

Para aclarar el significado de '/' adicional en resolución, hice lo siguiente en un shell:

mkdir this_is_dir
ln -s this_is_dir this_is_link
rm this_is_link

Todo estuvo bien, porque this_is_link es un enlace simbólico, y simplemente lo eliminé. Pero al intentarlo:

mkdir this_is_dir
ln -s this_is_dir this_is_link
rm this_is_link/

Se hizo eco rm: cannot remove 'this_is_link/': Is a directory

Bueno, el final '/' causó el seguimiento del enlace simbólico, pensé. Entonces, probé otro comando:rmdir this_is_link/

Y salió un resultado divertido: rmdir: failed to remove 'this_is_link/': Not a directory

No es lo que esperaba. Entonces le pedí a mi amigo que confirmara si se podía obtener el mismo resultado en su sistema. Tenía una versión de coreutils más baja que yo. Y el resultado fue sorprendente, no importa rmo rmdir 'this_is_link/', se Not a directoryproduce el mismo error .

Y otro amigo acaba de probarlo en su Mac OS, el resultado es: rm=> 'Es un directorio', rmdir=> el directorio se eliminó con éxito, el enlace permaneció .

¿Hay alguna especificación sobre el comportamiento exacto de la resolución de ruta?

ymfoi
fuente

Respuestas:

7

La especificación POSIX / Single Unix especifica que un nombre de ruta con una barra inclinada final debe referirse a un directorio (ver definiciones base §4.11 resolución de nombre de ruta ). foo/de hecho se define como equivalente a foo/.(para propósitos de resolución de ruta, no cuando se manipulan nombres de archivos; basenamee dirnameignora las barras diagonales finales). La mayoría de las implementaciones respetan esto, pero hay algunas excepciones.

Esto explica el comportamiento de rm this_is_link/: es equivalente a rm this_is_link/., donde el argumento es claramente un directorio.

rmdir this_is_link/debería referirse de manera similar al directorio. Que no lo haga en su máquina es un error en GNU coreutils. OSX se está comportando correctamente aquí.

Gilles 'SO- deja de ser malvado'
fuente
Esto es exactamente lo que necesitaba, gracias chico!
ymfoi
-1

Mi toma:

  • '' rm link / '' falla porque rm mira el último carácter, ve que es una barra oblicua, da el diagnóstico (no realmente correcto) que vio;
  • '' rmdir link / '' falla bien: el enlace no es un directorio, es un enlace simbólico
  • '' rm link '' tendrá éxito correctamente

Por cierto, la resolución de ruta tiene muy poco que ver con esto, solo parece estar '' rm '' cortando una esquina en lugar de (correctamente) invocar "stat" en un argumento (que es lo que está haciendo rmdir).

Salud.

Forma de vida alienígena
fuente
1
En realidad, lo contrario parece ser cierto: rmllama a stat (bueno, newfstatat, en realidad, con la AT_SYMLINK_NOFOLLOWopción) y se niega a continuar, mientras que rmdir realmente llama a rmdir (2), pero obtiene ENOTDIR.
Ansgar Esztermann el
@AnsgarEsztermann AT_SYMLINK_NOFOLLOWevitará que siga el enlace simbólico, por lo que rm debería eliminar el enlace en lugar de imprimir "No es un directorio" que no coincide con la circunstancia.
ymfoi
De una breve verificación con stat (1), la barra inclinada anulará la opción. La salida de staty stat -Ldifiere solo si el argumento se proporciona sin una barra inclinada final.
Ansgar Esztermann el
@AnsgarEsztermann Oh, ya veo ... Gracias. ¿Qué hay de los diferentes efectos en diferentes entornos? ¿Algunas ideas?
ymfoi
1
Es lo contrario: en la máquina de ymfoi, rmse comporta correctamente y rmdirno lo es. El seguimiento /debe obligarlos a tratar su argumento como un directorio, según el estándar POSIX. Vea mi respuesta para referencias .
Gilles 'SO- deja de ser malvado'