Como posso encontrar o programa que estou escondendo no bash

2

Digamos que eu tenha PATH="home/bob/bin:/usr/bin" . Eu estou escrevendo um script bash /home/bob/bin/foo que vai fazer alguns munging e depois chamar /usr/bin/foo . Claro que eu quero poder usar este script em diferentes sistemas que possuem diferentes estruturas de caminho. Na prática, o verdadeiro foo pode estar em muitos lugares diferentes, então eu quero apenas encontrá-lo no PATH. Meu novo script foo também está no meu caminho, então não posso simplesmente chamar o foo, o que resultará em uma chamada recursiva.

Existe uma maneira fácil de fazer isso em um script bash? (Além de fazer um loop através dos elementos do PATH e fazer a busca manualmente?)

    
por matt 03.04.2015 / 00:05

4 respostas

2

Você sempre pode obter o caminho para o segundo foo com:

foo=$(type -Pa foo | tail -n+2 | head -n1)

(os caminhos de arquivo fornecidos não contêm caracteres de nova linha).

Tenha em atenção que pode ser um caminho relativo que deixaria de ser válido depois de executar cd .

Você poderia então fazer:

hash -p "$foo" foo

Então que foo será invocado quando você executar foo .

    
por 03.04.2015 / 00:49
1

Eu não acho que haja uma maneira mais fácil de fazer isso de forma robusta do que enumerar os diretórios em PATH . Não é difícil.

#!/bin/bash
set -f; IFS=:
for d in $PATH; do
  if [[ -f $d/foo && -x $d/foo && ! $d/foo -ef /home/bob/bin/foo ]]; then
    exec "$d/foo" "$@"
    exit 126
  fi
done
echo "$0: foo (real) not found in PATH"
exit 127

Eu suponho que não há entradas vazias no PATH. Entradas vazias do PATH são ruins, escreva . explicitamente (ou melhor, não inclua nada).

Se você só executar foo na linha de comando e não em outros programas, faça-o uma função em vez de um script. A partir da função, execute command foo para ocultar a função.

    
por 03.04.2015 / 01:47
0

Se foo é importante, deve ser configurado no script. Isso eu acho que é uma boa prática, porque você, então, EXPLICITAMENTE o relaciona com o script. Eu não gosto de indireção, coisas implícitas ou ocultas ... scripts devem ser muito simples se forem implantados.

Caso contrário, se você insistir em encontrá-lo, então ele pode ser encontrado fazendo

whereisfoo="$(which foo)"

Se isso não for suficiente, temo que o que você está fazendo seja muito complexo.

    
por 03.04.2015 / 00:53
0

Aqui está uma abordagem que acredito ser ligeiramente menos confuso do que a resposta de Gilles (embora eu admita que isso seja um julgamento subjetivo).

#!/bin/sh
this_dir=$(dirname "$0")        # Alternatively, hard-code this as this_dir=$HOME/bin
redacted_PATH=$(echo ":${PATH}:" | sed -e "s:\:$this_dir\::\::" -e "s/^://" -e 's/:$//')
if obscured_prog=$(PATH=$redacted_PATH which foo)
then
            ⋮           # Munging to do before running /usr/bin/foo
        "$(obscured_prog)" argument(s)          # may be "$@", but might not be.
            ⋮           # Munging to do after running /usr/bin/foo
else
        echo "$0: foo (real) not found in PATH."
            ⋮           # Any code that you want to do anyway.
fi

Isso constrói redacted_PATH para ser $PATH menos o diretório $HOME/bin onde esta cópia privada de foo reside. echo ":${PATH}:" adiciona dois pontos no início e no final de $PATH , então cada componente será precedido e seguido por dois pontos até o primeiro e o último. O sed procura por

: $this_dir :

(com espaços adicionados para "clareza") e substitui por

:

isto é, excede $this_dir de ":${PATH}:" . Em seguida, remove os dois pontos do início e do fim.

Em seguida, definimos temporariamente PATH para $redacted_PATH e procure por foo usando which . Se tiver êxito, obtemos um caminho completo para ele (por exemplo, /bin/foo ou /usr/bin/foo ), que usamos para executar a cópia real (pública / compartilhada / do sistema) de foo . Como alteramos PATH apenas temporariamente, /bin/foo tem acesso ao ambiente do usuário $PATH , e assim, se /bin/foo executar brillig , ele poderá encontrar $HOME/bin/brillig (se existir).

Isso terá um problema se $HOME/bin aparecer em $PATH várias vezes, mas isso não é muito difícil de remediar.

    
por 03.04.2015 / 07:03