Скрипт оболочки Unix узнайте, в каком каталоге находится файл скрипта?

Скрипт оболочки Unix узнайте, в каком каталоге находится файл скрипта?

28.10.2008 11:19:24 Просмотров 28 Источник

В принципе, мне нужно запустить скрипт с путями, связанными с расположением файла скрипта оболочки, как я могу изменить текущий каталог на тот же каталог, где находится файл скрипта?

У вопроса есть решение - Посмотреть?

https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides#comment50026817_242538
Это действительно дубликат? Этот вопрос касается "сценария оболочки unix", другой-конкретно Bash.
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides#comment63164805_242538
@BoltClock: этот вопрос был неправильно закрыт. Связанный вопрос - о Баше. Этот вопрос касается программирования оболочки Unix. Обратите внимание, что принятые ответы совершенно разные!
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides#comment63165077_242538
@Dietrich Epp: вы правы. Похоже, выбор Аскером принятого ответа и добавление тега [bash] (вероятно, в ответ на это) привели меня к тому, что я пометил вопрос как дубликат в ответ на флаг.
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides#comment82154360_242538
Google привел меня сюда, когда я искал чистую реализацию решения в posix. После небольшого поиска я наткнулся на этот очень подробный ответ, объясняющий, почему это невозможно сделать, и способ обойти его, используя поддержку популярных оболочек. stackoverflow.com/a/29835459/816584
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides#comment86947121_242538
Не может вывод команды " pwd " быть назначен переменной в начале сценария,а затем использовать переменную через сценарий. Не уверен, правильно ли я понял вопрос

Ответы - Скрипт оболочки Unix узнайте, в каком каталоге находится файл скрипта? / Unix shell script find out which directory the script file resides?

Является ответом!
TheMarko

28.10.2008 11:26:03

В Баш, вы должны получить то, что вам нужно, как это:

#!/usr/bin/env bash

BASEDIR=$(dirname "$0")
echo "$BASEDIR"
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/242550#comment2456498_242550
Это не работает, если вы вызвали скрипт через символическую ссылку в другом каталоге. Чтобы сделать эту работу, вам readlinkreadlink (см. ответ Эла ниже)
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/242550#comment15303075_242550
В bash безопаснее использовать $BASH_SOURCEвместо $0, потому $0не всегда содержит путь вызываемого скрипта,например, при "поиске" скрипта.
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/242550#comment36761506_242550
$BASH_SOURCEспецифичен для Bash, речь идет о скрипте оболочки в целом.
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/242550#comment38664226_242550
CUR_PATH=$(pwd); echo $CUR_PATH
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/242550#comment38734973_242550
@auraham: CUR_PATH=$(pwd)или pwdвозвращают текущий каталог (который не обязательно должен быть родительским dir скриптов)!
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/242550#comment53661071_242550
Это не будет работать с символическими ссылками. Проверьте мое, надеюсь, более последовательное решение здесь github.com/lingtalfi/printScriptDir/blob/master/... , он обрабатывает символьные ссылки, относительные пути, абсолютные пути, протестированные на linux и macOsX
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/242550#comment55895546_242550
Я попробовал метод, рекомендованный @mklement0, используя $BASH_SOURCE, и он возвращает то, что мне нужно. Мой сценарий вызывается из другого сценария ,и $0в то время .возвращает правильный подкаталог (в моем случае $BASH_SOURCE).
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/242550#comment55900622_242550
@BillLynch: это верно лишь частично: скрипт в пути, который вызывается непосредственно через его строку shebang, содержит полный путь скрипта в $0. В отличие от этого , если вы делаете bash <nameOfScriptInPath>, это не делает - но этот метод вызова необычен и нецелесообразен (в сторону: Bash и Ksh поддерживают этот метод вызова, Dash и Zsh-нет). В любом случае, $BASH_SOURCE-это правильная переменная для использования в Bash. (Также: $0должен быть дважды закавычен в ответе.)
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/242550#comment63311945_242550
@CecilCurry, да это идиотизм. Этот ответ неверен по многим причинам. Когда он работает, это текущий каталог, а не каталог, в котором находится файл сценария. Но даже тогда она не исчезает . и..\
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/242550#comment72928729_242550
Как вы решаете".."в путь? (например, $PWD/$BASH_SOURCE= = foo/../bar)
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/242550#comment76727590_242550
@thang он печатает не текущий каталог, а относительный каталог скрипта.
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/242550#comment76890927_242550
@jamo, ты прав. вот что я имел в виду. я просто запустил его в то время как в содержащем dir и он возвращает ./
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/242550#comment89139084_242550
Путь scriptpath="$( CD-диск "$(каталог "$0")" ; фрд -П )" , на основании этого ответа stackoverflow.com/questions/4774054
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/242550#comment103458708_242550
Этот ответ будет просто вернуть "."
Mez

28.10.2008 11:29:17

Предполагая, что вы используете Баш

#!/bin/bash

current_dir=$(pwd)
script_dir=$(dirname $0)

echo $current_dir
echo $script_dir

Этот скрипт должен напечатать каталог, в котором вы находитесь, а затем каталог, в котором находится скрипт. Например, при вызове его из /с помощью скрипта в /home/mez/, он выводит

/
/home/mez

Помните, что при назначении переменных из выходных данных команды, оберните команду в $(и)- или вы не получите желаемый результат.

https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/242557#comment72632093_242557
Это не работает, когда я вызываю скрипт из текущего каталога.
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/242557#comment79688519_242557
@EricWang вы всегда находитесь в текущем каталоге.
foo

14.01.2009 10:32:14

Это должно сделать трюк.:

echo `pwd`/`dirname $0`

Он может выглядеть некрасиво в зависимости от того, как он был вызван и cwd, но должен привести вас туда, куда вам нужно идти (или вы можете настроить строку, если вам интересно, как она выглядит).

https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/444349#comment38735419_444349
проблема StackOverflow escape здесь: это, конечно, должно выглядеть так: `pwd`/`dirname $0`, но все еще может потерпеть неудачу на символьных ссылках
al.

28.10.2009 07:28:27

Оригинальное сообщение содержит решение (игнорируйте ответы, они не добавляют ничего полезного). Интересная работа осуществляется упомянутых команд Unix readlink с опцией -f. Работает, когда скрипт вызывается как по абсолютному, так и по относительному пути.

Для Баш, ш, КШ:

#!/bin/bash 
# Absolute path to this script, e.g. /home/user/bin/foo.sh
SCRIPT=$(readlink -f "$0")
# Absolute path this script is in, thus /home/user/bin
SCRIPTPATH=$(dirname "$SCRIPT")
echo $SCRIPTPATH

Для tcsh, csh:

#!/bin/tcsh
# Absolute path to this script, e.g. /home/user/bin/foo.csh
set SCRIPT=`readlink -f "$0"`
# Absolute path this script is in, thus /home/user/bin
set SCRIPTPATH=`dirname "$SCRIPT"`
echo $SCRIPTPATH

Смотрите также: https://stackoverflow.com/a/246128/59087

https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/1638397#comment5288371_1638397
Это самый лучший способ. Примечание. ответ "проверено" не будет работать, если вы сделаете: ./myscript.sh ...что бы сообщить, что каталог есть ".- это всегда даст вам абсолютный путь.
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/1638397#comment7033763_1638397
Примечание: не все системы имеют readlink. Вот почему я рекомендовал использовать pushd / popd (встроенные модули для bash).
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/1638397#comment14793240_1638397
Опция-fдля readlinkделает что-то другое в OS X (Lion) и, возможно, BSD. stackoverflow.com/questions/1055671/…
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/1638397#comment15303203_1638397
Чтобы прояснить @Ergwun комментарий: -f не поддерживается на OS X вообще (как Лев); там вы можете либо его удалить, либо -f делать с разрешения только один уровень косвенности, например, pushd "$(dirname "$(readlink "$BASH_SOURCE" || echo "$BASH_SOURCE")")", или вы можете свернуть свой собственный рекурсивный ссылку-скрипт, как показано в связанном пост.
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/1638397#comment33962253_1638397
Я до сих пор не понимаю, зачем ОП понадобился абсолютный путь. Учет "."должно работать нормально, если вы хотите получить доступ к файлам относительно пути скриптов, и вы назвали скрипт like ./myscript.sh
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/1638397#comment34116030_1638397
@EdH OP запросил пути, связанные с расположением файла сценария оболочки. Я понимаю это как относительный путь, а не абсолютный путь.
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/1638397#comment41226402_1638397
@StefanHaberl я думаю, что это было бы проблемой, если бы вы запустили скрипт, в то время как ваш текущий рабочий каталог отличался от расположения скрипта (напримерsh /some/other/directory/script.sh), в данном случае . будет вашим инвалидов, не /some/other/directory
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/1638397#comment50800285_1638397
Это не работает, если сценарий является исходным кодом. В этом случае $0 покажет только имя оболочки
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/1638397#comment68958656_1638397
объединив эту информацию с комментарием mklement0 к принятому ответу, я придумал HERE=$(dirname $(readlink -f $BASH_SOURCE))/я включил завершающую косую черту, чтобы предотвратить неудачи, подобные этой sudo rm-rf ${AccidentallyUndefinedVariable}/
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/1638397#comment85974750_1638397
Это намного лучше, чем ответ Демарко, и я должен изучить новую функцию, но она все еще очень глючит. Это не сработает, если вы запускаете скрипт из того же dir ($0=./script в этом случае и readlink не будет знать, что с ним делать) и он не будет работать, если вы используете запуск скрипта через относительные части (ex. ../ scriptfolder / script). У меня есть решение для этого. Я поставлю его после того, как проверю его в течение нескольких дней.
docwhat

18.03.2010 11:09:00

Если вы используете Баш....

#!/bin/bash

pushd $(dirname "${0}") > /dev/null
basedir=$(pwd -L)
# Use "pwd -P" for the path without links. man bash for more info.
popd > /dev/null

echo "${basedir}"
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/2473033#comment7033782_2473033
Вы можете заменить pushd/ popdна cd $(dirname "${0}")и cd -чтобы заставить его работать на других оболочках, если у них есть pwd -L.
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/2473033#comment34495400_2473033
почему вы используете pushd и popd здесь?
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/2473033#comment34546997_2473033
Поэтому мне не нужно хранить исходный каталог в переменной. Это шаблон, который я часто использую в функциях и тому подобном. Он очень хорошо гнездится, и это хорошо.
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/2473033#comment57031464_2473033
Он по-прежнему хранится в памяти-в переменной-независимо от того, ссылаются на переменную в вашем скрипте или нет. Кроме того, я считаю, что стоимость выполнения pushd и popd намного перевешивает экономию от не создания локальной переменной Bash в вашем скрипте, как в циклах процессора, так и в удобочитаемости.
blueyed

14.01.2011 07:50:23

cd $(dirname $(readlink -f $0))
ranamalo

06.06.2011 08:26:21

Как предполагает темарко:

BASEDIR=$(dirname $0)
echo $BASEDIR

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

Чтобы обойти эту проблему используйте:

current_dir=$(pwd)
script_dir=$(dirname $0)

if [ $script_dir = '.' ]
then
script_dir="$current_dir"
fi

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

Steven Penny

19.12.2012 10:30:58

Вдохновленный ответом синеглазого

read < <(readlink -f $0 | xargs dirname)
cd $REPLY
Daniel

05.04.2013 06:35:57

Более ранний комментарий к ответу сказал это, но его легко пропустить среди всех других ответов.

При использовании bash:

echo this file: "$BASH_SOURCE"
echo this dir: "$(dirname "$BASH_SOURCE")"

Справочное Руководство Bash, 5.2 Переменные Bash

https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/15824974#comment66566445_15824974
Только этот работает со скриптом в окружающем пути, большинство проголосовавших не работают. Спасибо!
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/15824974#comment83278451_15824974
Вместо этого следует использовать dirname "$BASH_SOURCE"для обработки пробелов в $BASH_SOURCE.
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/15824974#comment94018522_15824974
Более явным способом печати каталога, согласно tool ShellCheck, будет: "$(dirname "${BASH_SOURCE{0}}")", поскольку BASH_SOURCE является массивом, и без подстрочного индекса первый элемент берется по умолчанию.
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/15824974#comment101384091_15824974
@AdrianM. , вы хотите скобки, а не фигурные скобки, для индекса: "$(dirname "${BASH_SOURCE[0]}")"
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/15824974#comment101705425_15824974
Мне это не подходит..печатает только точку (т. е. текущий каталог, предположительно)
Ján Sáreník

11.05.2017 05:58:04

Давайте сделаем его POSIX oneliner:

a="/$0"; a=${a%/*}; a=${a#/}; a=${a:-.}; BASEDIR=$(cd "$a"; pwd)

Испытано на многих Борн-совместимых оболочках, включая BSD.

Насколько я знаю, я-автор, и я поместил его в общественное достояние. Для получения дополнительной информации см.: https://www.jasan.tk/posts/2017-05-11-posix_shell_dirname_replacement/

https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/43919044#comment77746573_43919044
как написано, cd: too many arguments, если пробелы в пути, и возвращает $PWD. (очевидное исправление, но просто показывает, сколько на самом деле крайних случаев)
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/43919044#comment84759515_43919044
Будет забавным. За исключением комментария от @michael, что это не удается с пробелами в пути... Есть ли решение для этого?
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/43919044#comment86322650_43919044
@spechter да, для этого есть решение. Смотрите обновлено jasan.tk/posix/2017/05/11/posix_shell_dirname_replacement
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/43919044#comment92650872_43919044
@Der_Meister-пожалуйста, уточните. Или написать (и, возможно, зашифровать) письмо джасану по адресу jasan.tk
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/43919044#comment92795428_43919044
ln-s / home / der / 1 / test / home / der / 2 / test & & / home / der / 2 / test = > / home / der / 2 (вместо этого должен отображаться путь к исходному сценарию)
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/43919044#comment92850091_43919044
@Der_Meister спасибо, например. Я понимаю вашу точку зрения. Это может быть канонизировано только с помощью readlink -fили realpath, насколько я знаю, и это было бы в значительной степени за пределами этой крошечной реализации POSIX-оболочки dirname, я думаю. Или у вас есть идея, как исправить это с помощью команд POSIX shell-only?
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/43919044#comment92891059_43919044
Я согласен с вами. Лично я использую readlink Linux и greadlink на macOS.
Alexandro de Oliveira

20.06.2017 08:59:47

Лучший ответ на этот вопрос был дан здесь:
Получение исходного каталога сценария Bash изнутри

И это так:

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

One-liner, который даст вам полное имя каталога скрипта независимо от того, откуда он вызывается.

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

#!/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" )" && pwd )"
if [ "$DIR" != "$RDIR" ]; then
  echo "DIR '$RDIR' resolves to '$DIR'"
fi
echo "DIR is '$DIR'"
michael

29.07.2017 09:58:12

Так много ответов, все правдоподобные, каждый с " ЗА " и "против" и немного отличающимися целями (которые, вероятно, должны быть указаны для каждого). Вот еще одно решение, которое отвечает основной цели и быть ясно и работать во всех системах, на всех Баш (никаких предположений о bash версии, или readlink или pwd ), а разумно ли то, что вы ожидаете произойдет (например, разрешение символических ссылок-задача интересная, но не обычно, что вы на самом деле хотите), обрабатывать граничные случаи, как пробелы в путях и т. д., игнорирует любые ошибки и использует нормальное значение по умолчанию, если есть какие-либо проблемы.

Каждый компонент хранится в отдельной переменной, которую можно использовать отдельно:

# script path, filename, directory
PROG_PATH=${BASH_SOURCE[0]}      # this script's name
PROG_NAME=${PROG_PATH##*/}       # basename of script (strip path)
PROG_DIR="$(cd "$(dirname "${PROG_PATH:-$PWD}")" 2>/dev/null 1>&2 && pwd)"
thebunnyrules

22.04.2018 12:53:43

ВСТУПЛЕНИЕ

Этот ответ исправляет очень сломанный, но шокирующе топовый ответ этой темы (написанный TheMarko):

#!/usr/bin/env bash

BASEDIR=$(dirname "$0")
echo "$BASEDIR"

Почему использование dirname "$0 " само по себе не работает?

dirname $0 будет работать только в том случае, если пользователь запускает скрипт очень специфическим способом. Мне удалось найти несколько ситуаций, в которых этот ответ не срабатывает и приводит к сбою сценария.

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

dirname "$0"

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

/some/path/./script argument1 argument2

$0= " / some / path/./скрипт"

dirname в основном находит последнее / в строке и усекает его там. Так что если вы это сделаете:

  dirname /usr/bin/sha256sum

вы получите: / usr / bin

Этот пример хорошо работает, потому что /usr / bin / sha256sum-это правильно отформатированный путь, но

  dirname "/some/path/./script"

не будет работать хорошо и даст вам:

  BASENAME="/some/path/." #which would crash your script if you try to use it as a path

Допустим, вы находитесь в том же dir, что и ваш скрипт, и запускаете его с помощью этой команды

./script   

$0 в этой ситуации будет ./script и dirname $0 дадут:

. #or BASEDIR=".", again this will crash your script

С помощью:

sh script

Без ввода полного пути также даст BASEDIR="."

Использование относительных каталогов:

 ../some/path/./script

Дает dirname $0 из:

 ../some/path/.

Если вы находитесь в каталоге /some и вызываете скрипт таким образом (обратите внимание на отсутствие / в начале, снова относительный путь):

 path/./script.sh

Вы получите это значение для dirname $0:

 path/. 

и./путь/./ script (другая форма относительного пути) дает:

 ./path/.

Только две ситуации, где basedir $0 будет работать, если пользователь использует sh или touch для запуска сценария, потому что оба приведут к $0:

 $0=/some/path/script

что даст вам путь, который вы можете использовать с dirname.

РЕШЕНИЕ

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

#!/bin/bash
#this script will only work in bash, make sure it's installed on your system.

#set to false to not see all the echos
debug=true

if [ "$debug" = true ]; then echo "\$0=$0";fi


#The line below detect script's parent directory. $0 is the part of the launch command that doesn't contain the arguments
BASEDIR=$(dirname "$0") #3 situations will cause dirname $0 to fail: #situation1: user launches script while in script dir ( $0=./script)
                                                                     #situation2: different dir but ./ is used to launch script (ex. $0=/path_to/./script)
                                                                     #situation3: different dir but relative path used to launch script
if [ "$debug" = true ]; then echo 'BASEDIR=$(dirname "$0") gives: '"$BASEDIR";fi                                 

if [ "$BASEDIR" = "." ]; then BASEDIR="$(pwd)";fi # fix for situation1

_B2=${BASEDIR:$((${#BASEDIR}-2))}; B_=${BASEDIR::1}; B_2=${BASEDIR::2}; B_3=${BASEDIR::3} # <- bash only
if [ "$_B2" = "/." ]; then BASEDIR=${BASEDIR::$((${#BASEDIR}-1))};fi #fix for situation2 # <- bash only
if [ "$B_" != "/" ]; then  #fix for situation3 #<- bash only
        if [ "$B_2" = "./" ]; then
                #covers ./relative_path/(./)script
                if [ "$(pwd)" != "/" ]; then BASEDIR="$(pwd)/${BASEDIR:2}"; else BASEDIR="/${BASEDIR:2}";fi
        else
                #covers relative_path/(./)script and ../relative_path/(./)script, using ../relative_path fails if current path is a symbolic link
                if [ "$(pwd)" != "/" ]; then BASEDIR="$(pwd)/$BASEDIR"; else BASEDIR="/$BASEDIR";fi
        fi
fi

if [ "$debug" = true ]; then echo "fixed BASEDIR=$BASEDIR";fi
Richard Gomes

09.06.2018 11:41:37

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

dir=$(dirname $(test -L "$BASH_SOURCE" && readlink -f "$BASH_SOURCE" || echo "$BASH_SOURCE"))

Кстати, я полагаю, что вы используете /bin / bash .

searchrome

12.09.2018 02:14:54

BASE_DIR="$(cd "$(dirname "$0")"; pwd)";
echo "BASE_DIR => $BASE_DIR"
https://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides/52293841#comment92145490_52293841
самый надежный не-Баш-специфический способ, который я знаю.
Rohith

02.04.2019 01:23:10

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

BASEDIR=$(dirname $(realpath "$0"))
echo "$BASEDIR"

Это работает как на linux, так и на macOS. Я не видел, чтобы здесь кто-нибудь упоминал о realpath. Не уверен, есть ли какие-либо недостатки в этом подходе.

на macOS необходимо установить coreutils, чтобы использовать realpath. Например: brew install coreutils.

Закрыть X