Encontre o caminho absoluto de um script

10

Em um script, recebo $0 o caminho relativo possível para ele. Para convertê-lo em absoluto, encontrei esta solução que não entendo:

abspath=$(cd ${0%/*} && echo $PWD/${0##*/})

Meu problema é a mágica dentro de ${0%/*} e ${0##*/} . Parece que o primeiro extrai o dirname e o segundo extrai o nome do arquivo, eu não entendo como.

    
por maaartinus 18.03.2011 / 14:00

5 respostas

8

Definições:

${string%substring} exclui a correspondência mais curta de $substring do final de $string .

${string##substring} exclui a correspondência mais longa de $substring do início de $string .

Seu exemplo:

abspath=$(cd ${0%/*} && echo $PWD/${0##*/})

${0%/*} exclui tudo após a última barra, fornecendo o nome do diretório do script (que pode ser um caminho relativo).

${0##*/} exclui tudo até a última barra, fornecendo apenas o nome do script.

Portanto, esse comando muda para o diretório do script e concatena o diretório de trabalho atual (fornecido por $PWD ) e o nome do script que fornece o caminho absoluto.

Para ver o que está acontecendo, tente:

echo ${0%/*}
echo ${0##*/}
    
por 18.03.2011 / 14:16
10

Shawn tinha a solução mais simples: readlink -f $0 . Se você quiser ter absoluta certeza de lidar com nomes de arquivos estranhos, você pode usar isto:

absolute_path_x="$(readlink -fn -- "$0"; echo x)"
absolute_path="${absolute_path_x%x}"

Documentação

    
por 18.03.2011 / 14:39
4

Aqui está uma maneira mais segura e mais legível de fazer esse trabalho:

abspath=$(unset CDPATH && cd "$(dirname "$0")" && echo $PWD/$(basename "$0"))

Notas:

  • Se $0 for um nome de arquivo simples sem caminho anterior, o script original falhará, mas o que foi fornecido aqui funcionará. (Não é um problema com $0 , mas poderia estar em outros aplicativos.)
  • Qualquer abordagem falhará se o caminho para o arquivo não existir. (Não é um problema com $0 , mas poderia estar em outros aplicativos.)
  • O unset é essencial se o usuário tiver CDPATH definido.
  • Ao contrário de readlink -f ou realpath , isso funcionará em versões não Linux do Unix (por exemplo, Mac OS X).
por 17.03.2013 / 09:12
2

Se você quiser aprender a expandir os parâmetros do Shell, leia-o em aqui , mas a Expansão nem sempre é uma boa escolha. Neste caso, quase todos os sistemas do tipo Unix possuem 2 bons utilitários:

basename
dirname

O primeiro extrairá o nome do arquivo, enquanto o segundo extrairá o caminho, então, se você tiver $ 0, diga:

dirname $0

E você conseguirá o caminho.

Felicidades

    
por 18.03.2011 / 15:05
0

Apresentando pwd, o bash embutido. Também encontrado no pacote GNU coreutils.

$ sh ./cygdrive/c/cygwin/home/../../../../home/jaroslav/tmp/somewhere.sh
$0: ./cygdrive/c/cygwin/home/../../../../home/jaroslav/tmp/somewhere.sh
cheeky binary from /home/jaroslav/tmp (/home/jaroslav/tmp)

$ cat /home/jaroslav/tmp/somewhere.sh

abs=$( cd 'dirname "$0"' ; pwd -P)
absBin=$( cd 'dirname "$0"' ; /bin/pwd -P)
echo \
$ sh ./cygdrive/c/cygwin/home/../../../../home/jaroslav/tmp/somewhere.sh
$0: ./cygdrive/c/cygwin/home/../../../../home/jaroslav/tmp/somewhere.sh
cheeky binary from /home/jaroslav/tmp (/home/jaroslav/tmp)

$ cat /home/jaroslav/tmp/somewhere.sh

abs=$( cd 'dirname "$0"' ; pwd -P)
absBin=$( cd 'dirname "$0"' ; /bin/pwd -P)
echo \%pre%: $0
echo cheeky binary from $abs \($absBin\)
: $0 echo cheeky binary from $abs \($absBin\)
    
por 18.03.2013 / 08:27

Tags