Получить исходный каталог скрипта Bash из самого скрипта - PullRequest
4414 голосов
/ 13 сентября 2008

Как получить путь к каталогу, в котором находится сценарий Bash , внутри этого сценария?

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

$ ./application

Ответы [ 58 ]

28 голосов
/ 30 декабря 2010

Получает текущий рабочий каталог в Mac OS X 10.6.6:

DIR=$(cd "$(dirname "$0")"; pwd)
27 голосов
/ 27 июля 2011
$(dirname "$(readlink -f "$BASH_SOURCE")")
27 голосов
/ 07 ноября 2018

Я устал заходить на эту страницу снова и снова, чтобы скопировать и вставить одну строку в принятый ответ. Проблема в том, что это нелегко понять и запомнить.

Вот скрипт, который легко запомнить:

DIR=$(dirname "${BASH_SOURCE[0]}")  # get the directory name
DIR=$(realpath "${DIR}")    # resolve its full path if need be
26 голосов
/ 16 сентября 2008

Это специфично для Linux, но вы можете использовать:

SELF=$(readlink /proc/$$/fd/255)
21 голосов
/ 06 марта 2013

Вот POSIX-совместимый однострочный:

SCRIPT_PATH=`dirname "$0"`; SCRIPT_PATH=`eval "cd \"$SCRIPT_PATH\" && pwd"`

# test
echo $SCRIPT_PATH
16 голосов
/ 19 февраля 2016

Вот простой, правильный способ:

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

Пояснение:

  • ${BASH_SOURCE[0]} - полный путь к скрипту. Значение этого будет правильным, даже когда сценарий получен, например, source <(echo 'echo $0') печатает bash , при замене на ${BASH_SOURCE[0]} будет напечатан полный путь к сценарию. (Конечно, это предполагает, что вы в порядке, принимая зависимость от Bash.)

  • readlink -f - Рекурсивно разрешает любые символические ссылки в указанном пути. Это расширение GNU, которое недоступно (например, в системах BSD). Если у вас Mac, вы можете использовать Homebrew для установки GNU coreutils и заменить его на greadlink -f.

  • И, конечно, dirname получает родительский каталог пути.

16 голосов
/ 09 сентября 2010

Я попробовал каждый из них, и ни один из них не сработал. Один был очень близко, но имел крошечную ошибку, которая сильно его сломала; они забыли завернуть путь в кавычки.

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

Попробуйте этот каталог для размера:

/ var / No one / Мысли / О пробелах / В каталоге / Имя / И вот ваш файл.текст

Это правильно, независимо от того, как и где вы его запускаете.

#!/bin/bash
echo "pwd: `pwd`"
echo "\$0: $0"
echo "basename: `basename "$0"`"
echo "dirname: `dirname "$0"`"

Итак, чтобы сделать его действительно полезным, вот как перейти в каталог запущенного скрипта:

cd "`dirname "$0"`"

Надеюсь, это поможет

15 голосов
/ 21 ноября 2012

Я бы использовал что-то вроде этого:

# retrieve the full pathname of the called script
scriptPath=$(which $0)

# check whether the path is a link or not
if [ -L $scriptPath ]; then

    # it is a link then retrieve the target path and get the directory name
    sourceDir=$(dirname $(readlink -f $scriptPath))

else

    # otherwise just get the directory name of the script path
    sourceDir=$(dirname $scriptPath)

fi
14 голосов
/ 14 апреля 2010

Небольшой пересмотр решения e-sat и 3bcdnlklvc04a указали в их ответ

SCRIPT_DIR=''
pushd "$(dirname "$(readlink -f "$BASH_SOURCE")")" > /dev/null && {
    SCRIPT_DIR="$PWD"
    popd > /dev/null
}    

Это должно работать во всех перечисленных случаях.

РЕДАКТИРОВАТЬ: предотвратить popd после неудачного pushd, благодаря konsolebox

13 голосов
/ 13 сентября 2008
#!/bin/sh
PRG="$0"

# need this for relative symlinks
while [ -h "$PRG" ] ; do
   PRG=`readlink "$PRG"`
done

scriptdir=`dirname "$PRG"`
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...