Обратитесь к файлу в том же каталоге сценария, найденного в $ PATH

У меня есть файл сценария bash, который помещается в некоторый каталог, добавленный в $ PATH, чтобы я мог вызвать скрипт из любого каталога.

Существует еще один текстовый файл в том же каталоге, что и скрипт. Интересно, как обращаться к текстовому файлу в скрипте?

Например, если скрипт просто выводит содержимое текстового файла, текстовый файл cat textfile не будет работать, поскольку при вызове сценария из другого каталога текстовый файл не найден.

Они должны работать одинаково, если нет символических ссылок (в расширении пути или самом скрипте):

  • MYDIR="$(dirname "$(realpath "$0")")"

  • MYDIR="$(dirname "$(which "$0")")"

  • Двухэтапная версия любого из перечисленных выше:

    MYSELF="$(realpath "$0")"

    MYDIR="${MYSELF%/*}"

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

[РЕДАКТИРОВАТЬ]: Похоже, что realpath не имеет преимущества по сравнению с readlink -f предложенным Калебом , вероятно, лучше использовать последнее. Мои тесты времени показывают, что это происходит быстрее.

$0 в скрипте будет полным путем к скрипту, а dirname будет иметь полный путь и даст вам только каталог, поэтому вы можете сделать это в текстовом файле cat:

 $ cat "$(dirname -- "$0")/textfile" 

Мои системы не имеют realpath как предложено rozcietrzewiacz .

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

 MYDIR="$(dirname "$(readlink -f "$0")")" 

Затем ваш текстовый файл может быть прочитан как переменная:

 TEXTFILE="$(<$MYDIR/textfile)" 

Вы можете поместить это в начало своего скрипта:

 cd "${BASH_SOURCE%/*}" || exit 

Внутренняя переменная bash BASH_SOURCE на самом деле представляет собой массив путей. Если вы развернете его как простую строку, например «$ BASH_SOURCE», вы получите первый элемент, который является именем пути исполняемой функции или скрипта.

Источник: http://mywiki.wooledge.org/BashFAQ/028

Я пытался это, и реальный путь не работал для меня. Решение, с которым я пошел, это:

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

До сих пор это хорошо. Я хотел бы знать, есть ли какие-либо потенциальные проблемы с этим подходом.

Я использую:

 #! /bin/sh - dir=$(cd -P -- "$(dirname -- "$0")" && pwd -P) || exit dosomethingwith "${dir%/}/some-file" 

Это POSIX и должен работать до тех пор, пока имя dirname $0 не заканчивается символами новой строки, а не - и $CDPATH не установлен (и, возможно, несколько других угловых случаев, если сценарий не был просмотрен в $PATH ) ,

Я всегда использую, чтобы найти полный путь к исполняемому файлу из PATH. Например:

which python

Если вы объедините это с командой dirname вы получите:

 wp=`which python` dn=`dirname $wp` ls $dn