Почему $0=/bin/foo, если /bin — это символическая ссылка

Почему $0=/bin/foo, если /bin — это символическая ссылка

Я установил свои bash-скрипты в /usr/bin/app.shи/usr/bin/lib.sh

app.shвключает

source "/usr/bin/lib.sh"

и lib.shвключает в себя

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

Когда я запускаю app.shиз оболочки, этот тест не проходит, потому что $0на самом деле /bin/app.sh. В файловой системе /binесть символическая ссылка на/usr/bin

Какой лучший способ lib.shопределить, включен ли он app.sh(в отличие от other-app.sh) таким образом, чтобы его не обманула среда? Я бы подумал, что абсолютные пути без символических ссылок справятся с этой задачей, но, видимо, нет.

решение1

Чтобы проверить, являются ли два файла одинаковыми, необходимо проверить номер индекса (инода), который отображается с помощью:

stat -L -c %i FilePath

Итак, ваш чек теперь будет выглядеть так:

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

Это работает независимо от каких-либо ссылок в пути к каталогу или даже символической или жесткой ссылки на сам файл.

Если быть совсем точным (спасибо @ilkkachu за указание на это), то вероятность того, что два разных файла с одинаковым именем могут иметь одинаковый inode в двух разных файловых системах, крайне мала. Чтобы этого избежать, включите в сравнение номер устройства:

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

решение2

readlink -f /path/to/whateverукажет вам канонический путь (который будет /usr/bin/app.shв вашем примере).

Отстраница руководства:

канонизировать, следуя каждой символической ссылке в каждом компоненте данного имени рекурсивно; все компоненты, кроме последнего, должны существовать

Связанный контент