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.