Obtenha o diretório atual do script (para que eu possa incluir arquivos sem caminhos relativos e executar o script de qualquer lugar)

1

Eu tenho o seguinte problema, meu script de shell contém algo como:

mydir=''

# config load
source $mydir/config.sh

.... execute various commands

Meu script é colocado no diretório do meu usuário .. digamos /home/bob/script.sh

Se eu estiver dentro do /home/bob dir e executar ./script.sh , tudo funcionará bem.

Se eu estiver fora e quiser usar o caminho absoluto /home/bob/script.sh , o arquivo config.sh não será recuperado corretamente.

Qual valor devo atribuir a $mydir para tornar o script executável em todos os caminhos sem dificuldades?

mydir=$(which command?)

PS: como bônus, por favor, forneça uma alternativa se o diretório script estiver dentro do $ PATH

    
por user3450548 31.03.2016 / 11:00

4 respostas

6

A variável $0 contém o caminho do script:

$ cat ~/bin/foo.sh
#!/bin/sh
echo $0

$ ./bin/foo.sh
./bin/foo.sh

$ foo.sh
/home/terdon/bin/foo.sh

$ cd ~/bin
$ foo.sh
./foo.sh

Como você pode ver, a saída depende da maneira como foi chamada, mas sempre retorna o caminho para o script em relação à maneira como o script foi executado. Você pode, portanto, fazer:

## Set mydir to the directory containing the script
## The ${var%pattern} format will remove the shortest match of
## pattern from the end of the string. Here, it will remove the
## script's name,. leaving only the directory. 
mydir="${0%/*}"

# config load
source "$mydir"/config.sh

Se o diretório estiver no seu $PATH , as coisas serão ainda mais simples. Você pode apenas executar source config.sh . Por padrão, source procurará arquivos nos diretórios em $PATH e fornecerá o primeiro que encontrar:

$ help source
source: source filename [arguments]
    Execute commands from a file in the current shell.

Read and execute commands from FILENAME in the current shell.  The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.

Se você tiver certeza de que seu config.sh é único ou, pelo menos, que é o primeiro encontrado em $PATH , é possível fornecê-lo diretamente. No entanto, sugiro que você não faça isso e se atenha ao primeiro método. Você nunca sabe quando outro config.sh pode estar no seu $PATH .

    
por 31.03.2016 / 11:12
6

Encontrou a solução:

mydir=$(dirname "$0")

Com isso, o script pode ser invocado de qualquer lugar sem throubles.

    
por 31.03.2016 / 11:11
4

Esse método é somente útil em um script bash .

Uso:

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

Como funciona:

BASH_SOURCE é uma variável de matriz cujos membros são os nomes de arquivos de origem nos quais os nomes de função de shell correspondentes na variável de matriz FUNCNAME estão definidos.

Então, com:

cd "$( dirname "${BASH_SOURCE[0]}" )"

você move para o diretório em que o script é colocado.

Em seguida, a saída de cd enviada para /dev/null , porque, às vezes, ela imprime algo em STDOUT. Por exemplo, se o seu $ CDPATH tiver .

e finalmente, executa:

pwd

que obtém a localização atual.

Fonte :

link

    
por 31.03.2016 / 13:24
1

Teste isso testado e verifique com shellcheck :

mydir="$(dirname "${0}")"
source "${mydir}"/config.sh
printf "read value of config_var is %s\n" "${config_var}"

O teste:

$ ls 
script.sh
config.sh
$ cat script.sh
#!/bin/bash --
mydir="$(dirname "${0}")"
source "${mydir}"/config.sh

printf "read value of config_var is %s\n" "${config_var}"

$ cat config.sh
config_var=super_value

$ mkdir "$(printf "testdir" "")"
$ mv *.sh *testdir
$ *testdir/script.sh
read value of config_var is super_value
    
por 31.03.2016 / 12:12