Что я хотел бы сделать, так это включить настройки из файла в мою текущую интерактивную оболочку bash следующим образом:
$. /path/to/some/dir/.settings
Проблема в том, что сценарий .settings также должен использовать символ "." оператор, чтобы включить другие файлы, подобные этому:
. .extra_settings
Как мне указать относительный путь для .extra_settings в файле .settings? Эти два файла всегда хранятся в одном каталоге, но путь к этому каталогу будет отличаться в зависимости от того, где эти файлы были установлены.
Оператор всегда знает / path / to / some / dir /, как показано выше. Как файлу .settings узнать каталог, в котором он установлен? Я бы предпочел не иметь процесс установки, в котором записывается имя установленного каталога.





Я пробовал возиться с вариантами $ (dirname $ 0), но это не удается, когда файл .settings включен с ".". Если бы я выполнял файл .settings вместо его включения, это решение работало бы. Вместо этого $ (dirname $ 0) всегда возвращает ".", Означающее текущий каталог. Это не удается, когда вы делаете что-то вроде этого:
$ cd / $. /some/path/.settings
Другой взгляд на проблему - если вы используете "." Чтобы установить переменные среды, другой стандартный способ сделать это - использовать команды настройки эхо-переменных вашего сценария, например:
# settings.sh
echo export CLASSPATH=${CLASSPATH}:/foo/bar
затем оцените результат:
eval $(/path/to/settings.sh)
Вот как работают такие пакеты, как модули. Этот способ также упрощает поддержку оболочек, производных от sh (X=...; export X) и csh (setenv X ...).
Мне нравится эта идея. Однако я не использую его, потому что из-за побочных эффектов файл .settings станет еще более нечитаемым, поскольку в нем уже есть множество экранирований для начала. См. ниже.
Я считаю, что $(dirname "$BASH_SOURCE") будет делать то, что вы хотите, пока файл, который вы получаете, является символической ссылкой нет.
Если файл, который вы получаете, может быть символической ссылкой, вы можете сделать что-то вроде следующего, чтобы получить истинный каталог:
PRG = "$BASH_SOURCE"
progname=`basename "$BASH_SOURCE"`
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG = "$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
dir=$(dirname "$PRG")
Идеально. $ (dirname "$ BASH_SOURCE") - это именно то, что я искал. Для моей цели я не особо беспокоюсь о символических ссылках. Спасибо всем, что откликнулись. Действительно хорошие ответы здесь.
Чтобы разрешить символические ссылки, вы можете просто сделать: dir=$(dirname $(readlink -f "$BASH_SOURCE"))
Такого рода работы. Он работает в том смысле, что вы можете использовать синтаксис $ (dirname $ 0) в файле .settings, чтобы определить его домашний адрес, поскольку вы выполняете этот сценарий в новой оболочке. Однако он добавляет дополнительный уровень свертки, где вам нужно изменить строки, такие как:
export MYDATE=$(date)
к
echo "export MYDATE=\$(date)"
Может это единственный выход?
Похоже, это также добавило бы сложности, если бы вы использовали функции оболочки. (Я искал способ сделать это, работающий как с ksh, так и с bash ...)
Вот какое изящное решение:
script_path = "${BASH_SOURCE[0]}"
script_dir = "$(cd "$(dirname "${script_path}")" && pwd)"
Однако это не сработает при поиске ссылок. В этом случае можно было бы сделать
script_path = "$(readlink -f "$(readlink "${BASH_SOURCE[0]}")")"
script_dir = "$(cd "$(dirname "${script_path}")" && pwd)"
На заметку:
${array[x]}, не совместимы с POSIX - но тогда массив BASH_SOURCE доступен только в Bash, в любом случаеreadlink не поддерживает -f, поэтому вам, возможно, придется установить GNU readlink, например, заваривать на brew install coreutils и заменить readlink на greadlink-e или -m вместо -f и, возможно, -n; см. справочную страницу ссылка для чтения для подробностейЗачем нужен [0]? @JasonDay не имеет этого в своем ответе.
BASH_SOURCE - это массив, представляющий стек вызовов, в котором первый элемент является текущим исполняемым скриптом.
Верно, вот как это делает ИНН. "innconfvar" (я думаю, так оно и называется) испускает переменные конфигурации как команды sh, csh или perl.