O local do script de origem não está disponível, a menos que você esteja usando um shell que ofereça extensões para a especificação POSIX. Você pode testar isso com o seguinte snippet:
env -i PATH=/usr/bin:/bin sh -c '. ./included.sh' | grep included
onde included.sh
contém
echo "$0"
set
No bash, o nome do script de origem está $BASH_SOURCE
. No zsh (no modo de compatibilidade zsh, não no modo de compatibilidade sh ou ksh), ele está $0
(observe que em uma função, $0
é o nome da função). No pdksh and dash, ele não está disponível. No ksh93, esse método não revela a solução, mas o caminho completo para o script incluído está disponível como ${.sh.file}
.
Se exigir bash ou ksh93 ou zsh for bom o suficiente, você pode usar este trecho:
if [ -n "$BASH_SOURCE" ]; then
this_script=$BASH_SOURCE
elif [ -n "$ZSH_VERSION" ]; then
setopt function_argzero
this_script=$0
elif eval '[[ -n ${.sh.file} ]]' 2>/dev/null; then
eval 'this_script=${.sh.file}'
else
echo 1>&2 "Unsupported shell. Please use bash, ksh93 or zsh."
exit 2
fi
Você pode tentar adivinhar a localização do script, observando quais arquivos o shell abriu. Experimentalmente, isso parece funcionar com o dash e o pdksh, mas não com o bash ou o ksh93, que pelo menos para um script curto, fechou o arquivo de script no momento em que o executava.
open_file=$(lsof -F n -p $$ | sed -n '$s/^n//p')
if [ -n "$open_file" ]; then
# best guess: $open_file is this script
fi
O script pode não ser o arquivo com o descritor de número mais alto se o script for originado em um script complexo que esteja sendo reproduzido com redirecionamentos. Você pode querer percorrer os arquivos abertos. Não é garantido que funcione de qualquer maneira. A única maneira confiável de localizar um script de origem é usar o bash, ksh93 ou zsh.
Se você puder alterar a interface, em vez de procurar seu script, faça com que ele imprima um snippet de shell a ser passado eval
no chamador. É o que os scripts para definir variáveis de ambiente geralmente fazem. Ele permite que seu script seja escrito independentemente dos caprichos do shell e da configuração do chamador.
#!/bin/sh
FOO_DIR=$(dirname -- "$0")
cat <<EOF
FOO_DIR='$(printf %s "$FOO_DIR" | sed "s/'/'\\''/g")'
PATH="\$PATH:$FOO_DIR/bin";
export FOO_DIR PATH
EOF
No chamador: eval "`/path/to/setenv`"