Como fazer um script que usa $0 funcionar quando está em $PATH?

Como fazer um script que usa $0 funcionar quando está em $PATH?

Eu tenho um script (~/.../gremlin) para o qual criei um link virtual:

ln -s ~/[...]/gremlin ~/sc/gremlin

~/sc/gremliné em $PATH.
Chamar o script funciona diretamente.
Chamar através do link não.
Ele usa dirname $0então não ganha nada.

Existe uma maneira de fazer essa configuração funcionar sem alterar o script e sem criar outro no lugar do soft link?

É assim que $0 é usado:

case `uname` in
  CYGWIN*)
    CP=$( echo `dirname $0`/../lib/*.jar . | sed 's/ /;/g')
    ;;
  *)
    CP=$( echo `dirname $0`/../lib/*.jar . | sed 's/ /:/g')
esac

Responder1

Se o uso de dirname $0é um problema ou não, dependerá decomoé usado. Sem mais detalhes, não podemos responder a isso.

Se (a) o uso de dirname $0for um problema e (b) você não puder alterar o script, a solução será substituir o soft link ~/sc/gremlinpor um script:

#!/bin/sh
exec ~/../gremlin "$@"

Desta forma, ~/../gremlinserá executado com um arquivo $0.

O uso de execsignifica que o processo que executa o script ~/../gremlinsubstituirá o processo em execução ~/sc/gremlin. Isso é mais eficiente do que manter ambos os processos até ~/../gremlinserem concluídos.

Responder2

Se você deseja derivar o ~/...diretório de $0, em vez de ~/scdentro do script, você pode fazer:

Se for um zshscript:

#! /bin/zsh -
dir=$0:A:h

Caso contrário, e desde que você tenha um readlinkcomando que se comporte como o do GNU (alguns sistemas possuem um realpathcomando que você pode usar):

#! /bin/sh -
dir=$(dirname -- "$(readlink -f -- "$0")")

readlink -fe $0:Adar-lhe ocanônicocaminho do arquivo, que é um caminho absoluto após a resolução de todos os links simbólicos em todos os componentes do caminho.

E então:

set -- "$dir"/../lib/*.jar .
case $(uname) in
  CYGWIN*) IFS=';';;
  *)       IFS=:;;
esac
CP="$*"

Ou:

case $(uname) in
  CYGWIN*) sep=';';;
  *)       sep=:;;
esac
CP=$(printf "%s$sep" "$dir"/../lib/*.jar).

Responder3

Como apontou @ john1024, o erro de digitação na pergunta do OP pode ser o objetivo da pergunta:

ln -s ~/.../gremlin ~/sc/gremlin

Embora alguns aplicativos respeitem os pontos triplos, os sistemas de arquivos Unix não. Seuconchaexpande o ~(til), não ln, então

    ln -s ~/../gremlin ~/sc/gremlin

expandiria o nome do caminho conforme esperado. Se o link já existir, você poderá substituí-lo usando a -fopção. No entanto, se o destino for um arquivo real, a -fopção substituirá silenciosamente o arquivo com um link simbólico. Você pode querer usar a -iopção que pelo menos informa que já existe algo lá.

Se quiser validar o link (provar que ele aponta para um arquivo), a -Lopção de lsé útil:

ls -lL ~/sc/gremlin

Se não for um arquivo, lsirá (dependendo da implementação) mostrar apenas um lpara o tipo (o primeiro caractere da listagem), com pontos de interrogação para os bits de permissão) ou alguma outra indicação de que não está apontando para um arquivo real (O OSX simplesmente se recusa a mostrar qualquer coisa neste caso, embora conte o tamanho do link simbólico no total).

Leitura adicional:

informação relacionada