Referindo-se a um arquivo relativo à execução do script

94

Em um script bash que estou escrevendo, uso sourcepara incluir a variável definida em um arquivo de configuração. O script a ser executado é act.sh, enquanto o script a ser sourced é act.conf.sh, então act.sheu tenho:

source act.conf.sh

No entanto, isso só funciona quando executado act.shno diretório que o contém, uma vez act.conf.shque se refere ao arquivo colocado sob o diretório de trabalho. Existe uma solução para fazer com que se refira ao arquivo relativo ao script em execução sem invocar cd? Obrigado.

Ryan Li
fonte

Respostas:

116

Consulte: Entrada nº 28 da FAQ do BASH: "Como determino a localização do meu script? Quero ler alguns arquivos de configuração do mesmo lugar."

Qualquer solução não vai funcionar 100% do tempo:

É importante perceber que no caso geral, esse problema não tem solução. Qualquer abordagem da qual você já deve ter ouvido falar, e qualquer abordagem que será detalhada a seguir, tem falhas e só funcionará em casos específicos. Em primeiro lugar, tente evitar o problema totalmente, não dependendo da localização do seu script!

Se você precisar escrever uma ferramenta muito reutilizável, usar o caminho correto como parâmetro para o seu script será o método mais confiável .

Supondo que seu script será executado apenas a partir de determinados shells, e apenas com um pouco de flexibilidade necessária, você provavelmente pode relaxar um pouco dessa paranóia. Ainda é bom olhar para as suas opções. Existem padrões comuns que as pessoas usam que são particularmente problemáticos.

Em particular, o FAQ recomenda evitar a $0variável muito comumente usada :

Nada do que lê $0jamais será à prova de balas, porque em $0si mesmo não é confiável.

Como alternativa, você pode usar $BASH_SOURCE. Algo assim:

source "${BASH_SOURCE%/*}/act.conf.sh"

Existem algumas ressalvas para essa solução também. Confira a página de perguntas frequentes para ver as compensações entre as diferentes soluções. Eles parecem ser recomendados cdem combinação com $BASH_SOURCEcasos em que funcionará para você, pois você obterá uma condição de erro útil quando ele não se expandir adequadamente.

Ignacio Vazquez-Abrams
fonte
1
Obrigado, eu usaria readlink. Não foi possível determinar as palavras-chave a serem pesquisadas, então postei a pergunta aqui ...
Ryan Li
9
Você pode inserir as informações relevantes na resposta caso o bash faq esteja desativado?
Merlyn Morgan-Graham
3
Link recomenda :,cd "${BASH_SOURCE%/*}" || exit ou read somevar < "${BASH_SOURCE%/*}/etc/somefile"Link Desencoraja fortemente $0 "Nada que leia $ 0 será à prova de balas, porque $ 0 em si não é confiável."
ThorSummoner
10
O que faz% / * após BASH_SOURCE e como?
Silicomancer
34

Veja isto: Bash: Como _melhor_ incluir outros scripts?

Eu sugiro usar:

source $(dirname $0)/act.conf.sh
vagovszkym
fonte
8
Esta não é a resposta que você busca. $0é inerentemente cheio de erros. Veja a resposta mais votada e aceita sobre o motivo, ou simplesmente leia mywiki.wooledge.org/BashFAQ/028 - uma breve solução alternativa para a pergunta feita é algo comosource "${BASH_SOURCE%/*}/act.conf.sh"
Merlyn Morgan-Graham
5

Experimente o seguinte:

source ${BASH_SOURCE[0]/%act.sh/act.conf.sh}
Sem noção
fonte