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.