Pregunta ¿Por qué $ 0 = / bin / foo cuando / bin es un enlace simbólico?


Instalé mis scripts bash en /usr/bin/app.sh y /usr/bin/lib.sh

app.sh incluye

source "/usr/bin/lib.sh"

y lib.sh incluye

if [ "/usr/bin/app.sh" == "$0"] ...

Cuando corro app.sh del shell, esta prueba falla porque $0 es en realidad /bin/app.sh. En el sistema de archivos, /bin es un enlace simbólico a /usr/bin

¿Cuál es la mejor manera de lib.sh para determinar si está siendo incluido por app.sh (Opuesto a other-app.sh) de tal manera que no sea engañado por el medio ambiente? Hubiera pensado que los caminos absolutos sin enlaces simbólicos habrían hecho el trabajo, pero aparentemente no.


1


origen




Respuestas:


Para verificar si dos archivos son iguales, debe verificar el número de índice (inode), que se muestra con:

stat -L -c %i FilePath

Entonces su cheque ahora se convierte en:

if [ $(stat -L -c %i "/usr/bin/app.sh") == $(stat -L -c %i "$0") ] ...

Esto funciona independientemente de cualquier enlace en la ruta del directorio, o incluso un enlace simbólico o difícil al archivo en sí.

Para ser estrictamente preciso (gracias a @ilkkachu por señalar esto), hay una posibilidad muy poco probable de que dos archivos diferentes con el mismo nombre puedan tener el mismo inodo en dos sistemas de archivos diferentes. Para evitar esto, incluya el número de dispositivo en la comparación:

if [ $(stat -L -c %d:%i "/usr/bin/app.sh") == $(stat -L -c %d:%i "$0") ] ...

2



En principio, la comparación de números de inodo solo es válida dentro del mismo sistema de archivos. Aunque es probable que no puedas golpear en una colisión por casualidad. - ilkkachu
@ilkkachu - Buen punto, que pasé por alto. He elaborado mi respuesta para tenerlo en cuenta. Gracias. - AFH


readlink -f /path/to/whatever le dirá la ruta canónica (que será /usr/bin/app.sh en tu ejemplo).

De la página man:

canonicalizar siguiendo cada enlace simbólico en cada componente del nombre dado recursivamente; todo menos el último componente debe existir


3