Ссылка на файл, относящийся к исполняемому сценарию

97

В написанном мной сценарии bash я использую sourceдля включения переменной, определенной в файле конфигурации. Скрипт, который должен быть выполнен act.sh, а скрипт, который должен быть sourced, есть act.conf.sh, поэтому у act.shменя есть:

source act.conf.sh

Однако это работает только при запуске act.shв каталоге, содержащем его, поскольку act.conf.shэто относится к файлу, помещенному в рабочий каталог. Есть ли решение, чтобы он ссылался на файл относительно исполняемого скрипта без вызова cd? Спасибо.

Райан Ли
источник

Ответы:

121

См. Статью № 28 часто задаваемых вопросов BASH: «Как определить местоположение моего скрипта? Я хочу прочитать некоторые файлы конфигурации из того же места».

Ни одно решение не будет работать в 100% случаев:

Важно понимать, что в общем случае эта проблема не имеет решения. Любой подход, о котором вы, возможно, слышали, и любой подход, который будет подробно описан ниже, имеет недостатки и будет работать только в определенных случаях. Прежде всего, постарайтесь полностью избежать проблемы, не полагаясь на местоположение вашего скрипта!

Если вам нужно написать очень многоразовый инструмент, то выбор правильного пути в качестве параметра вашего скрипта будет самым надежным методом .

Предполагая, что ваш скрипт будет запускаться только из определенных оболочек, и только с небольшой необходимой гибкостью, вы, вероятно, сможете немного ослабить эту паранойю. Все еще хорошо рассмотреть ваши варианты. Есть распространенные шаблоны, которые люди используют, и которые вызывают особые проблемы.

В частности, в FAQ рекомендуется избегать очень часто используемой $0переменной:

Ничто из того, что читает $0, никогда не будет пуленепробиваемым, потому что $0само по себе ненадежно.

В качестве альтернативы вы можете использовать $BASH_SOURCEвместо него. Что-то вроде этого:

source "${BASH_SOURCE%/*}/act.conf.sh"

К этому решению тоже есть некоторые предостережения. Посетите страницу часто задаваемых вопросов, чтобы увидеть компромиссы между различными решениями. Кажется, они рекомендуют cdв сочетании с $BASH_SOURCEв тех случаях, когда это сработает для вас, поскольку вы получаете удобное состояние ошибки, когда он не может правильно развернуться.

Игнасио Васкес-Абрамс
источник
1
Спасибо, воспользуюсь readlink. Не удалось определить ключевые слова для поиска, поэтому разместил вопрос здесь ....
Райан Ли
9
Можете ли вы вставить соответствующую информацию в ответ, если часто задаваемые вопросы bash не работают?
Мерлин Морган-Грэм
3
Линк рекомендует: cd "${BASH_SOURCE%/*}" || exitили read somevar < "${BASH_SOURCE%/*}/etc/somefile", Ссылка категорически обескураживает $0 «Ничто, что читает $ 0, никогда не будет пуленепробиваемым, потому что $ 0 сам по себе ненадежен».
ThorSummoner
10
Что делает% / * после BASH_SOURCE и как?
Silicomancer
1
gnu.org/software/bash/manual/html_node/…
Игнасио Васкес-Абрамс,
34

Видеть это: Bash: Как _ лучше_ включать другие сценарии?

Предлагаю использовать:

source $(dirname $0)/act.conf.sh
ваговский
источник
8
Это не тот ответ, который вы ищете. $0по своей сути глючит. Посмотрите, почему большинство проголосовало и приняло ответ, или просто прочтите mywiki.wooledge.org/BashFAQ/028 - короткий способ решения заданного вопроса выглядит примерно такsource "${BASH_SOURCE%/*}/act.conf.sh"
Мерлин Морган-Грэм,
5

Попробуйте следующее:

source ${BASH_SOURCE[0]/%act.sh/act.conf.sh}
Невежественный
источник
1

Обычно я добавляю это поверх своих скриптов.

cd $(dirname $BASH_SOURCE)

Затем весь последующий код выполняется относительно этого пути сценария.

Гаян Виракутти
источник