Nextrp [CPP] RU + Many GEOs Игра на карте России | NEXTRP

Get the source directory of a Bash script from within the script itself

bash directory

1515666 просмотра

30 ответа

48575 Репутация автора

How do I get the path of the directory in which a Bash script is located, inside that script?

For instance, let's say I want to use a Bash script as a launcher for another application. I want to change the working directory to the one where the Bash script is located, so I can operate on the files in that directory, like so:

$ ./application
Автор: Jiaaro Источник Размещён: 12.09.2008 08:39

Ответы (30)


788 плюса

112675 Репутация автора

Используйте 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
Автор: matt b Размещён: 12.09.2008 08:49

97 плюса

12198 Репутация автора

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

#!/bin/bash

scriptdir=`dirname "$BASH_SOURCE"`

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

Автор: Mr Shark Размещён: 12.09.2008 08:50

34 плюса

0 Репутация автора

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

./script

/usr/bin/script

script

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

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

Автор: Jim Размещён: 13.09.2008 01:07

13 плюса

0 Репутация автора

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

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

scriptdir=`dirname "$PRG"`
Автор: Monkeyboy Размещён: 13.09.2008 01:28

56 плюса

13314 Репутация автора

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`

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

Автор: SpoonMeiser Размещён: 15.09.2008 07:55

26 плюса

3931 Репутация автора

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

SELF=$(readlink /proc/$$/fd/255)
Автор: Steve Baker Размещён: 16.09.2008 07:55

177 плюса

301 Репутация автора

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дается в полном пути, независимо от того, как это называется.
Просто убедитесь, что вы нашли это в начале скрипта.

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

Автор: user25866 Размещён: 07.10.2008 04:12

7 плюса

5026 Репутация автора

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

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

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

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

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

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

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

Автор: Matt Tardiff Размещён: 14.10.2008 04:39

6011 плюса

200843 Репутация автора

Решение
#!/bin/bash

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

is a useful one-liner which will give you the full directory name of the script no matter where it is being called from.

It will work as long as the last component of the path used to find the script is not a symlink (directory links are OK). If you also want to resolve any links to the script itself, you need a multi-line solution:

#!/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запустили другой каталог перед запуском этого фрагмента, результат может быть неверным!

Кроме того, следите за побочными эффектами $CDPATHgetchas и stderr, если у пользователя есть умный переопределенный cd для перенаправления вывода на stderr (включая escape-последовательности, например, при вызове update_terminal_cwd >&2на Mac). Добавление >/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'
Автор: dogbane Размещён: 29.10.2008 08:36

102 плюса

3465 Репутация автора

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

`dirname $0`

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

$(dirname "$0")
Автор: Fabien Размещён: 03.12.2008 12:57

7 плюса

26067 Репутация автора

Хм, если в пути basename и dirname просто не собираются его обрезать, и пройти путь сложно (что если родитель не экспортировал PATH!). Однако оболочка должна иметь открытый дескриптор своего скрипта, а в bash дескриптор # 255.

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

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

Автор: Joshua Размещён: 24.01.2009 05:01

438 плюса

3017 Репутация автора

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

dirname "$0"

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

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

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

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

Вот скрипт, демонстрирующий каждый из них, whatdir.sh:

#!/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
Автор: phatblat Размещён: 26.09.2009 08:38

14 плюса

1772 Репутация автора

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

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

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

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

Автор: Fuwjax Размещён: 13.04.2010 10:12

16 плюса

0 Репутация автора

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

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

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

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

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

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

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

cd "`dirname "$0"`"

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

Автор: Mike Bethany Размещён: 09.09.2010 07:19

5 плюса

1 Репутация автора

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

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

Не красиво, но это делает работу.

Автор: tigfox Размещён: 22.09.2010 11:22

32 плюса

661 Репутация автора

SCRIPT_DIR=$( cd ${0%/*} && pwd -P )
Автор: P M Размещён: 07.10.2010 05:34

28 плюса

1 Репутация автора

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

DIR=$(cd "$(dirname "$0")"; pwd)
Автор: Pubguy Размещён: 30.12.2010 07:20

28 плюса

1 Репутация автора

$(dirname "$(readlink -f "$BASH_SOURCE")")
Автор: test11 Размещён: 27.07.2011 07:40

11 плюса

14571 Репутация автора

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

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

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

Автор: hurrymaplelad Размещён: 16.09.2011 07:05

9 плюса

1 Репутация автора

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

real=$(realpath $(dirname $0))
Автор: DarkPark Размещён: 06.02.2012 10:43

15 плюса

93 Репутация автора

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

# 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
Автор: Nicolas Размещён: 21.11.2012 03:57

21 плюса

21 Репутация автора

Вот POSIX-совместимая строка:

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

# test
echo $SCRIPT_PATH
Автор: lamawithonel Размещён: 06.03.2013 07:07

11 плюса

243 Репутация автора

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

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

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

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

Это немного уродливо, но исправление компактно и легко для понимания. Мы не используем только примитивы bash, но я согласен с этим, потому readlinkчто значительно упрощает задачу. Оператор echo Xadd добавляет 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"
Автор: billyjmc Размещён: 21.04.2013 01:40

8 плюса

80097 Репутация автора

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

CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"

поскольку такие команды, как realpathили readlinkмогут быть недоступны (в зависимости от операционной системы).

Примечание: в Bash рекомендуется использовать ${BASH_SOURCE[0]}вместо $0, в противном случае путь может сломаться при поиске файла ( source/ .).

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

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

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

Связанные с:

Автор: kenorb Размещён: 28.11.2013 12:05

8 плюса

2029 Репутация автора

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

#!/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
Автор: Geoff Nixon Размещён: 21.12.2013 05:47

10 плюса

7516 Репутация автора

Для систем, имеющих GNU coreutils readlink (например, linux):

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

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

Автор: user1338062 Размещён: 28.05.2014 07:16

63 плюса

1581 Репутация автора

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

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

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

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

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

Автор: Simon Rigét Размещён: 12.02.2016 11:40

16 плюса

13444 Репутация автора

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

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получает родительский каталог пути.

Автор: James Ko Размещён: 19.02.2016 08:30

7 плюса

146 Репутация автора

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

    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

Автор: User8461 Размещён: 09.03.2018 12:56

28 плюса

7456 Репутация автора

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

Вот простой в запоминании скрипт:

DIR=$(dirname "${BASH_SOURCE[0]}")  # get the directory name
DIR=$(realpath "${DIR}")    # resolve its full path if need be
Автор: Thamme Gowda Размещён: 07.11.2018 04:30
Вопросы из категории :
32x32