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

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

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

app.shincluye

source "/usr/bin/lib.sh"

e lib.shincluye

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

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

¿Cuál es la mejor manera de lib.shdeterminar si está incluido app.sh(a diferencia de other-app.sh) de tal manera que el medio ambiente no lo engañe? Pensé que las rutas absolutas sin enlaces simbólicos habrían funcionado, pero aparentemente no.

Respuesta1

Para verificar si dos archivos son iguales, debe verificar el número de índice (inodo), 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 de un enlace físico o simbólico al archivo mismo.

Para ser estrictamente exactos (gracias a @ilkkachu por señalar esto), existe una posibilidad muy poco probable de que dos archivos diferentes con el mismo nombre tengan 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") ] ...

Respuesta2

readlink -f /path/to/whateverle dirá la ruta canónica (que estará /usr/bin/app.shen su ejemplo).

Dela página de manual:

canonicalizar siguiendo cada enlace simbólico en cada componente del nombre de pila de forma recursiva; todos menos el último componente deben existir

información relacionada