Как bash script знает каталог, в котором он установлен, когда он создан. оператор?

Что я хотел бы сделать, так это включить настройки из файла в текущую интерактивную оболочку bash следующим образом:

$./path/to/some/dir/.settings

Проблема заключается в том, что .settings script также необходимо использовать ".". для включения других файлов:

..extra_settings

Как ссылаться на относительный путь для .extra_settings в файле .settings? Эти два файла всегда хранятся в одном каталоге, но путь к этому каталогу будет отличаться в зависимости от того, где эти файлы были установлены.

Оператор всегда знает путь /path/to/some/dir/, как показано выше. Как файл .settings знает каталог, в котором он установлен? Я бы предпочел не иметь процесс установки, который записывает имя установленного каталога.

Ответ 1

Я считаю, что $(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")

Ответ 2

Вот что может быть элегантным решением:

script_dir=$( cd $( dirname "${BASH_SOURCE[0]}" ) && pwd )

Однако это не будет работать при поиске ссылок. В этом случае можно сделать

script_dir=$( readlink -f $( readlink "${BASH_SOURCE[0]}" )

Будьте уверены, что массивы типа ${array[x]} не совместимы с POSIX. Разумеется, массив BASH_SOURCE доступен только в Bash.

Ответ 3

Разный подход к проблеме - если вы используете "." для установки переменных среды другой стандартный способ сделать это состоит в том, чтобы иметь команды настройки параметров эхо-команды script, например:

# settings.sh
echo export CLASSPATH=${CLASSPATH}:/foo/bar

то eval вывод:

eval $(/path/to/settings.sh)

Как пакеты, такие как modules работают. Этот способ также облегчает поддержку оболочек, полученных из sh (X=...; export X) и csh (setenv X ...)

Ответ 4

Я попытался возиться с вариантами $(dirname $0), но он терпит неудачу, когда файл .settings включен в ".". Если бы я исполнял файл .settings, а не включал его, это решение сработало бы. Вместо этого $(dirname $0) всегда возвращает ".", Что означает текущий каталог. Это происходит при выполнении примерно так:

$cd/ $./some/path/.settings

Ответ 5

Такие работы. Он работает в том смысле, что вы можете использовать синтаксис $(dirname $0) в файле .settings для определения своего дома, поскольку вы выполняете этот script в новой оболочке. Однако он добавляет дополнительный слой свертки, где вам нужно изменить строки, такие как:

export MYDATE=$(date)

к

echo "export MYDATE=\$(date)"

Возможно, это единственный способ?