Могу ли я получить абсолютный путь к текущему скрипту в KornShell?
Можно ли узнать полный путь к скрипту, который в данный момент выполняется в KornShell (ksh)?
т.е. если мой сценарий находится в /opt/scripts/myscript.ksh
Могу ли я программно найти внутри этого скрипта /opt/scripts/myscript.ksh
?
Спасибо,
12 ответов
Вы можете использовать:
## __SCRIPTNAME - name of the script without the path
##
typeset -r __SCRIPTNAME="${0##*/}"
## __SCRIPTDIR - path of the script (as entered by the user!)
##
__SCRIPTDIR="${0%/*}"
## __REAL_SCRIPTDIR - path of the script (real path, maybe a link)
##
__REAL_SCRIPTDIR=$( cd -P -- "$(dirname -- "$(command -v -- "$0")")" && pwd -P )
В оболочке korn все эти решения за $0 не работают, если вы используете исходный код в рассматриваемом сценарии. Правильный способ получить то, что вы хотите, это использовать $_
$ cat bar
echo dollar under is $_
echo dollar zero is $0
$ ./bar
dollar under is ./bar
dollar zero is ./bar
$ . ./bar
dollar under is bar
dollar zero is -ksh
Обратите внимание на последнюю строку там? Используйте $_. По крайней мере, в Корне. YMMV в bash, csh и др..
Ну, это заняло у меня некоторое время, но этот настолько прост, что кричит.
_SCRIPTDIR=$(cd $(dirname $0);echo $PWD)
поскольку CD работает в порожденной оболочке с $(), это не влияет на текущий скрипт.
Как был вызван скрипт, хранится в переменной $0. Ты можешь использовать readlink
чтобы получить абсолютное имя файла:
readlink -f "$0"
Переменная $RPATH содержит относительный путь к реальному файлу или реальный путь для реального файла.
CURPATH=$( cd -P -- "$(dirname -- "$(command -v -- "$0")")" && pwd -P )
CURLOC=$CURPATH/`basename $0`
if [ `ls -dl $CURLOC |grep -c "^l" 2>/dev/null` -ne 0 ];then
ROFFSET=`ls -ld $CURLOC|cut -d ">" -f2 2>/dev/null`
RPATH=`ls -ld $CURLOC/$ROFFSET 2>/dev/null`
else
RPATH=$CURLOC
fi
echo $RPATH
readlink -f
было бы лучше, если бы он был переносимым, потому что он разрешает все ссылки, найденные как для каталогов, так и для файлов.
На Mac OS X нет readlink -f
(кроме, может быть, через MacPort), так что вы можете использовать только readlink
чтобы получить назначение конкретного файла символьной ссылки.
$(cd -P ... pwd -P)
Техника хороша, но работает только для разрешения ссылок на каталоги, ведущие к скрипту, она не работает, если сам скрипт является символической ссылкой
Кроме того, один случай, который не был упомянут: когда вы запускаете скрипт, передавая его в качестве аргумента в оболочку (/bin/sh /path/to/myscript.sh
), $0
не может использоваться в этом случае
Я взглянул на mysql "binaries", многие из них на самом деле являются скриптами оболочки; и теперь я понимаю, почему они просят --basedir
возможность или необходимость запуска из определенного рабочего каталога; это потому, что нет хорошего решения, чтобы найти целевой скрипт
Вот что я сделал:
if [[ $0 != "/"* ]]; then
DIR=`pwd`/`dirname $0`
else
DIR=`dirname $0`
fi
Попробуйте какую команду.
which scriptname
даст вам полное имя скрипта вместе с его абсолютным путем
Это также работает, хотя и не даст "истинного" пути, если это ссылка. Это проще, но менее точно.
SCRIPT_PATH="$(whence ${0})"
Я усовершенствовал ответ Эдварда Штодта, чтобы иметь возможность работать с символическими ссылками абсолютного пути, а также с цепочками ссылок.
DZERO=$0
while true; do
echo "Trying to find real dir for script $DZERO"
CPATH=$( cd -P -- "$(dirname -- "$(command -v -- "$DZERO")")" && pwd -P )
CFILE=$CPATH/`basename $DZERO`
if [ `ls -dl $CFILE | grep -c "^l" 2>/dev/null` -eq 0 ];then
break
fi
LNKTO=`ls -ld $CFILE | cut -d ">" -f2 | tr -d " " 2>/dev/null`
DZERO=`cd $CPATH ; command -v $LNKTO`
done
Ужасно, но работает... После запуска это путь $CPATH и файл $CFILE
Использование $_ обеспечивает последнюю команду.
>source my_script
Работает, если я введу команду дважды:
>source my_script
>source my_script
Если я использую другую последовательность команд:
>who
>source my_script
Переменная $_ возвращает "кто"