Получите исходный каталог сценария Bash изнутри самого сценария.

StackOverflow https://stackoverflow.com/questions/59895

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

$ ./application
Это было полезно?

Решение

#!/bin/bash

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"

— это полезная однострочная программа, которая предоставит вам полное имя каталога сценария независимо от того, откуда он вызывается.

Это будет работать до тех пор, пока последний компонент пути, использованного для поиска скрипта, не является символической ссылкой (ссылки на каталоги допустимы).Если вы также хотите разрешить любые ссылки на сам скрипт, вам понадобится многострочное решение:

#!/bin/bash

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
  DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
  SOURCE="$(readlink "$SOURCE")"
  [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"

Последний будет работать с любой комбинацией псевдонимов, source, bash -c, символические ссылки и т. д.

Остерегаться:если вы cd в другой каталог перед запуском этого фрагмента, результат может быть неверным!

Также следите за $CDPATH ошибки, и побочные эффекты вывода stderr, если пользователь разумно переопределил cd, чтобы вместо этого перенаправить вывод на stderr (включая escape-последовательности, например, при вызове update_terminal_cwd >&2 на Маке).Добавление >/dev/null 2>&1 в конце твоего cd команда позаботится об обеих возможностях.

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

#!/bin/bash

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
  TARGET="$(readlink "$SOURCE")"
  if [[ $TARGET == /* ]]; then
    echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
    SOURCE="$TARGET"
  else
    DIR="$( dirname "$SOURCE" )"
    echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
    SOURCE="$DIR/$TARGET" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
  fi
done
echo "SOURCE is '$SOURCE'"
RDIR="$( dirname "$SOURCE" )"
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
if [ "$DIR" != "$RDIR" ]; then
  echo "DIR '$RDIR' resolves to '$DIR'"
fi
echo "DIR is '$DIR'"

И он напечатает что-то вроде:

SOURCE './scriptdir.sh' is a relative symlink to 'sym2/scriptdir.sh' (relative to '.')
SOURCE is './sym2/scriptdir.sh'
DIR './sym2' resolves to '/home/ubuntu/dotfiles/fo fo/real/real1/real2'
DIR is '/home/ubuntu/dotfiles/fo fo/real/real1/real2'

Другие советы

Использовать dirname "$0":

#!/bin/bash
echo "The script you are running has basename `basename "$0"`, dirname `dirname "$0"`"
echo "The present working directory is `pwd`"

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

[matt@server1 ~]$ pwd
/home/matt
[matt@server1 ~]$ ./test2.sh
The script you are running has basename test2.sh, dirname .
The present working directory is /home/matt
[matt@server1 ~]$ cd /tmp
[matt@server1 tmp]$ ~/test2.sh
The script you are running has basename test2.sh, dirname /home/matt
The present working directory is /tmp

Команда dirname является самой простой: она просто анализирует путь до имени файла из переменной $0 (имя сценария):

dirname "$0"

Но Мэтт Б Как указано выше, возвращаемый путь различается в зависимости от того, как вызывается сценарий.pwd не выполняет эту работу, поскольку он сообщает вам только текущий каталог, а не каталог, в котором находится сценарий.Кроме того, если выполняется символическая ссылка на скрипт, вы получите (вероятно, относительный) путь к тому месту, где находится ссылка, а не к самому скрипту.

Некоторые другие упомянули ссылка для чтения команду, но в самом простом случае вы можете использовать:

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

readlink преобразует путь сценария в абсолютный путь от корня файловой системы.Таким образом, любые пути, содержащие одиночные или двойные точки, тильды и/или символические ссылки, будут преобразованы в полный путь.

Вот сценарий, демонстрирующий каждый из них: чтодир.ш:

#!/bin/bash
echo "pwd: `pwd`"
echo "\$0: $0"
echo "basename: `basename $0`"
echo "dirname: `dirname $0`"
echo "dirname/readlink: $(dirname $(readlink -f $0))"

Запуск этого скрипта в моем домашнем каталоге по относительному пути:

>>>$ ./whatdir.sh 
pwd: /Users/phatblat
$0: ./whatdir.sh
basename: whatdir.sh
dirname: .
dirname/readlink: /Users/phatblat

Опять же, но используя полный путь к скрипту:

>>>$ /Users/phatblat/whatdir.sh 
pwd: /Users/phatblat
$0: /Users/phatblat/whatdir.sh
basename: whatdir.sh
dirname: /Users/phatblat
dirname/readlink: /Users/phatblat

Теперь меняем каталоги:

>>>$ cd /tmp
>>>$ ~/whatdir.sh 
pwd: /tmp
$0: /Users/phatblat/whatdir.sh
basename: whatdir.sh
dirname: /Users/phatblat
dirname/readlink: /Users/phatblat

И, наконец, использование символической ссылки для выполнения скрипта:

>>>$ ln -s ~/whatdir.sh whatdirlink.sh
>>>$ ./whatdirlink.sh 
pwd: /tmp
$0: ./whatdirlink.sh
basename: whatdirlink.sh
dirname: .
dirname/readlink: /Users/phatblat
pushd . > /dev/null
SCRIPT_PATH="${BASH_SOURCE[0]}"
if ([ -h "${SCRIPT_PATH}" ]); then
  while([ -h "${SCRIPT_PATH}" ]); do cd `dirname "$SCRIPT_PATH"`; 
  SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done
fi
cd `dirname ${SCRIPT_PATH}` > /dev/null
SCRIPT_PATH=`pwd`;
popd  > /dev/null

Работает для всех версий, включая

  • при вызове через мягкую ссылку множественной глубины,
  • когда файл это
  • когда скрипт вызывается командой "source"ака . (точка) оператор.
  • когда аргумент $0 изменяется из вызывающего абонента.
  • "./script"
  • "/full/path/to/script"
  • "/some/path/../../another/path/script"
  • "./some/folder/script"

В качестве альтернативы, если сам сценарий bash является относительная символическая ссылка ты хотеть чтобы следовать по нему и вернуть полный путь к связанному скрипту:

pushd . > /dev/null
SCRIPT_PATH="${BASH_SOURCE[0]}";
if ([ -h "${SCRIPT_PATH}" ]) then
  while([ -h "${SCRIPT_PATH}" ]) do cd `dirname "$SCRIPT_PATH"`; SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done
fi
cd `dirname ${SCRIPT_PATH}` > /dev/null
SCRIPT_PATH=`pwd`;
popd  > /dev/null

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

Этот комментарий и код с авторским левом, выбираемая лицензия под GPL2.0 или более поздней версии или CC-SA 3.0 (CreativeCommons Share Alike) или более поздней версии.(с) 2008.Все права защищены.Никаких гарантий.Вы были предупреждены.
http://www.gnu.org/licenses/gpl-2.0.txt
http://creativecommons.org/licenses/by-sa/3.0/
18eedfe1c99df68dc94d4a94712a71aaa8e1e9e36cacf421b9463dd2bbaa02906d0d6656

Короткий ответ:

`dirname $0`

или (предпочтительно):

$(dirname "$0")

Вы можете использовать $BASH_SOURCE

#!/bin/bash

scriptdir=`dirname "$BASH_SOURCE"`

Обратите внимание, что вам нужно использовать #!/bin/bash, а не #!/bin/sh, поскольку это расширение bash.

Это должно сделать это:

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

Работает с символическими ссылками и пробелами в пути.См. справочные страницы для имя каталога и ссылка для чтения.

Редактировать:

Судя по комментариям, он не работает с Mac OS.Я понятия не имею, почему это так.Какие-либо предложения?

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

Однако, dirname дает именно часть имени файла, относящуюся к каталогу, которая, скорее всего, будет относиться к текущему рабочему каталогу.Если вашему сценарию по какой-то причине необходимо сменить каталог, то вывод dirname становится бессмысленным.

Я предлагаю следующее:

#!/bin/bash

reldir=`dirname $0`
cd $reldir
directory=`pwd`

echo "Directory is $directory"

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

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

Хотя просто

cd `dirname $0`

решает конкретный сценарий в вопросе, я считаю, что абсолютный путь к более полезному в целом.

Я не думаю, что это так просто, как представляют другие.pwd не работает, поскольку текущий каталог не обязательно является каталогом со сценарием.$0 также не всегда содержит информацию.Рассмотрим следующие три способа вызова сценария.

./script

/usr/bin/script

script

В первом и третьем способах $0 не имеет полной информации о пути.Во втором и третьем pwd не работают.Единственный способ получить каталог третьим способом — это пробежаться по пути и найти файл с правильным совпадением.По сути, код должен будет переделать то, что делает ОС.

Один из способов сделать то, что вы просите, — просто жестко закодировать данные в каталоге /usr/share и ссылаться на них по полному пути.Данные в любом случае не должны находиться в каталоге /usr/bin, так что, вероятно, это то, что нужно сделать.

SCRIPT_DIR=$( cd ${0%/*} && pwd -P )

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

DIR=$(cd "$(dirname "$0")"; pwd)
$(dirname "$(readlink -f "$BASH_SOURCE")")

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

Вот легко запоминающийся сценарий:

DIR=$(dirname "${BASH_SOURCE[0]}")  # get the directory name
DIR=$(realpath "${DIR}")    # resolve its full path if need be

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

SELF=$(readlink /proc/$$/fd/255)

Вот однострочный файл, совместимый с POSIX:

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

# test
echo $SCRIPT_PATH

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

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

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

/var/Никто/Мысль/О существовании пространств/В каталоге/Имя/И вот ваш файл.текст

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

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

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

cd "`dirname "$0"`"

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

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

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

Объяснение:

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

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

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

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

# 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

Небольшая доработка решения e-satis и 3bcdnlklvc04a, указанного в их ответ

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

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

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

#!/bin/sh
PRG="$0"

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

scriptdir=`dirname "$PRG"`

$_ Стоит упомянуть как альтернативу $0.Если вы запускаете скрипт из bash, принятый ответ можно сократить до:

DIR="$( dirname "$_" )"

Обратите внимание, что это должен быть первый оператор в вашем сценарии.

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

  • Абсолютные пути или относительные пути
  • Программные ссылки на файлы и каталоги
  • Вызов как script, bash script, bash -c script, source script, или . script
  • Пробелы, табуляции, новые строки, Юникод и т. д.в каталогах и/или имени файла
  • Имена файлов, начинающиеся с дефиса

Если вы работаете из Linux, кажется, что использование proc handle — лучшее решение для поиска полностью разрешенного источника текущего сценария (в интерактивном сеансе ссылка указывает на соответствующий /dev/pts/X):

resolved="$(readlink /proc/$$/fd/255 && echo X)" && resolved="${resolved%$'\nX'}"

В этом есть немного уродства, но исправление компактное и легкое для понимания.Мы не используем только примитивы bash, но меня это устраивает, потому что readlink значительно упрощает задачу.А echo X добавляет X до конца строки переменной, чтобы любые конечные пробелы в имени файла не были съедены, а замена параметра ${VAR%X} в конце строки избавляется от X.Потому что readlink добавляет собственную новую строку (которая обычно была бы съедена при подстановке команды, если бы не наш предыдущий трюк), от нее тоже придется избавиться.Проще всего это сделать с помощью $'' схема цитирования, которая позволяет нам использовать escape-последовательности, такие как \n для обозначения новой строки (именно так вы можете легко создавать каталоги и файлы с коварными именами).

Вышеупомянутое должно покрыть ваши потребности в поиске текущего сценария в Linux, но если у вас нет proc файловая система в вашем распоряжении или если вы пытаетесь найти полностью разрешенный путь к какому-либо другому файлу, возможно, приведенный ниже код окажется для вас полезным.Это лишь небольшая модификация приведенного выше однострочника.Если вы экспериментируете со странными именами каталогов/файлов, проверьте вывод с помощью обоих ls и readlink информативен, так как ls выведет «упрощенные» пути, заменив ? для таких вещей, как новые строки.

absolute_path=$(readlink -e -- "${BASH_SOURCE[0]}" && echo x) && absolute_path=${absolute_path%?x}
dir=$(dirname -- "$absolute_path" && echo x) && dir=${dir%?x}
file=$(basename -- "$absolute_path" && echo x) && file=${file%?x}

ls -l -- "$dir/$file"
printf '$absolute_path: "%s"\n' "$absolute_path"

Попробуйте использовать:

real=$(realpath $(dirname $0))

Для систем, имеющих ссылку на чтение GNU coreutils (например.Линукс):

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

Нет необходимости использовать BASH_SOURCE когда $0 содержит имя файла сценария.

Так...Я верю, что у меня есть этот.Опоздали на вечеринку, но я думаю, что некоторые оценят это, если они наткнутся на эту тему.Комментарии должны объяснить.

#!/bin/sh # dash bash ksh # !zsh (issues). G. Nixon, 12/2013. Public domain.

## 'linkread' or 'fullpath' or (you choose) is a little tool to recursively
## dereference symbolic links (ala 'readlink') until the originating file
## is found. This is effectively the same function provided in stdlib.h as
## 'realpath' and on the command line in GNU 'readlink -f'.

## Neither of these tools, however, are particularly accessible on the many
## systems that do not have the GNU implementation of readlink, nor ship
## with a system compiler (not to mention the requisite knowledge of C).

## This script is written with portability and (to the extent possible, speed)
## in mind, hence the use of printf for echo and case statements where they
## can be substituded for test, though I've had to scale back a bit on that.

## It is (to the best of my knowledge) written in standard POSIX shell, and
## has been tested with bash-as-bin-sh, dash, and ksh93. zsh seems to have
## issues with it, though I'm not sure why; so probably best to avoid for now.

## Particularly useful (in fact, the reason I wrote this) is the fact that
## it can be used within a shell script to find the path of the script itself.
## (I am sure the shell knows this already; but most likely for the sake of
## security it is not made readily available. The implementation of "$0"
## specificies that the $0 must be the location of **last** symbolic link in
## a chain, or wherever it resides in the path.) This can be used for some
## ...interesting things, like self-duplicating and self-modifiying scripts.

## Currently supported are three errors: whether the file specified exists
## (ala ENOENT), whether its target exists/is accessible; and the special
## case of when a sybolic link references itself "foo -> foo": a common error
## for beginners, since 'ln' does not produce an error if the order of link
## and target are reversed on the command line. (See POSIX signal ELOOP.)

## It would probably be rather simple to write to use this as a basis for
## a pure shell implementation of the 'symlinks' util included with Linux.

## As an aside, the amount of code below **completely** belies the amount
## effort it took to get this right -- but I guess that's coding for you.

##===-------------------------------------------------------------------===##

for argv; do :; done # Last parameter on command line, for options parsing.

## Error messages. Use functions so that we can sub in when the error occurs.

recurses(){ printf "Self-referential:\n\t$argv ->\n\t$argv\n" ;}
dangling(){ printf "Broken symlink:\n\t$argv ->\n\t"$(readlink "$argv")"\n" ;}
errnoent(){ printf "No such file: "$@"\n" ;} # Borrow a horrible signal name.

# Probably best not to install as 'pathfull', if you can avoid it.

pathfull(){ cd "$(dirname "$@")"; link="$(readlink "$(basename "$@")")"

## 'test and 'ls' report different status for bad symlinks, so we use this.

 if [ ! -e "$@" ]; then if $(ls -d "$@" 2>/dev/null) 2>/dev/null;  then
    errnoent 1>&2; exit 1; elif [ ! -e "$@" -a "$link" = "$@" ];   then
    recurses 1>&2; exit 1; elif [ ! -e "$@" ] && [ ! -z "$link" ]; then
    dangling 1>&2; exit 1; fi
 fi

## Not a link, but there might be one in the path, so 'cd' and 'pwd'.

 if [ -z "$link" ]; then if [ "$(dirname "$@" | cut -c1)" = '/' ]; then
   printf "$@\n"; exit 0; else printf "$(pwd)/$(basename "$@")\n"; fi; exit 0
 fi

## Walk the symlinks back to the origin. Calls itself recursivly as needed.

 while [ "$link" ]; do
   cd "$(dirname "$link")"; newlink="$(readlink "$(basename "$link")")"
   case "$newlink" in
    "$link") dangling 1>&2 && exit 1                                       ;;
         '') printf "$(pwd)/$(basename "$link")\n"; exit 0                 ;;
          *) link="$newlink" && pathfull "$link"                           ;;
   esac
 done
 printf "$(pwd)/$(basename "$newlink")\n"
}

## Demo. Install somewhere deep in the filesystem, then symlink somewhere 
## else, symlink again (maybe with a different name) elsewhere, and link
## back into the directory you started in (or something.) The absolute path
## of the script will always be reported in the usage, along with "$0".

if [ -z "$argv" ]; then scriptname="$(pathfull "$0")"

# Yay ANSI l33t codes! Fancy.
 printf "\n\033[3mfrom/as: \033[4m$0\033[0m\n\n\033[1mUSAGE:\033[0m   "
 printf "\033[4m$scriptname\033[24m [ link | file | dir ]\n\n         "
 printf "Recursive readlink for the authoritative file, symlink after "
 printf "symlink.\n\n\n         \033[4m$scriptname\033[24m\n\n        "
 printf " From within an invocation of a script, locate the script's "
 printf "own file\n         (no matter where it has been linked or "
 printf "from where it is being called).\n\n"

else pathfull "$@"
fi

Попробуйте следующее кросс-совместимое решение:

CWD="$(cd -P -- "$(dirname -- "$0")" && pwd -P)"

как realpath или readlink команды не всегда доступны (в зависимости от операционной системы) и ${BASH_SOURCE[0]} доступен только в оболочке bash.

Альтернативно вы можете попробовать следующую функцию в bash:

realpath () {
  [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}

Эта функция принимает 1 аргумент.Если аргумент уже имеет абсолютный путь, выведите его как есть, в противном случае выведите $PWD переменная + аргумент имени файла (без ./ префикс).

Связанный:

Хм, если на пути базовое название и дирноме просто не собирается разрезать его, и идти по пути сложно (что, если родитель не экспортировал путь!).Тем не менее, оболочка должна иметь открытую ручку для своего сценария, а в ударе ручка № 255.

SELF=`readlink /proc/$$/fd/255`

работает для меня.

Подводя итог многим ответам:

    Script: "/tmp/src dir/test.sh"
    Calling folder: "/tmp/src dir/other"

Используемые команды

    echo Script-Dir : `dirname "$(realpath $0)"`
    echo Script-Dir : $( cd ${0%/*} && pwd -P )
    echo Script-Dir : $(dirname "$(readlink -f "$0")")
    echo
    echo Script-Name : `basename "$(realpath $0)"`
    echo Script-Name : `basename $0`
    echo
    echo Script-Dir-Relative : `dirname "$BASH_SOURCE"`
    echo Script-Dir-Relative : `dirname $0`
    echo
    echo Calling-Dir : `pwd`

Выход:

     Script-Dir : /tmp/src dir
     Script-Dir : /tmp/src dir
     Script-Dir : /tmp/src dir

     Script-Name : test.sh
     Script-Name : test.sh

     Script-Dir-Relative : ..
     Script-Dir-Relative : ..

     Calling-Dir : /tmp/src dir/other

Видетьhttps://pastebin.com/J8KjxrPF

Это работает в bash-3.2:

path="$( dirname "$( which "$0" )" )"

Вот пример его использования:

Скажем, у вас есть ~/бин каталог, который находится в вашем $PATH.У вас есть сценарий А внутри этого каталога.Это источниксценарий ~/bin/lib/B.Вы знаете, где находится включенный скрипт относительно исходного (подкаталог библиотека), но не там, где он находится относительно текущего каталога пользователя.

Это решается следующим (внутри А):

source "$( dirname "$( which "$0" )" )/lib/B"

Неважно, где находится пользователь и как он вызывает скрипт, это всегда сработает.

Ни один из них не работал для сценария bash, запущенного Finder в OS X - в итоге я использовал:

SCRIPT_LOC="`ps -p $$ | sed /PID/d | sed s:.*/Network/:/Network/: |
sed s:.*/Volumes/:/Volumes/:`"

Некрасиво, но со своей задачей справляется.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top