A localização 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á em $BASH_SOURCE
. Em zsh (no modo de compatibilidade zsh, não no modo de compatibilidade sh ou ksh), está em $0
(observe que em uma função, $0
é o nome da função). Em pdksh e dash, não está disponível. Em 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 precisar de 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 dash e pdksh, mas não com bash ou ksh93, que pelo menos para um script curto, fechou o arquivo de script no momento em que ele executou o script.
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 numeração mais alta, se o script for originado em um script complexo que está sendo reproduzido com redirecionamentos. Você pode querer percorrer os arquivos abertos. Isso não é garantido para funcionar de qualquer maneira. A única forma confiável de localizar um script de origem é usar bash, ksh93 ou zsh.
Se você puder alterar a interface, em vez de terceirizar seu script, peça ao script para imprimir um fragmento de shell a ser passado para eval
no chamador. Isso é o que os scripts para definir variáveis de ambiente normalmente fazem. Ele permite que seu script seja escrito independentemente dos caprichos da configuração de shell e shell 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'"