Como encontrar de forma confiável o caminho completo de um programa no PATH?

12

Eu preciso encontrar o caminho de um determinado programa no PATH usando um script de shell. O caminho deve ser o caminho completo real do programa, que pode ser passado posteriormente para uma das funções exec* , que não pesquisa o próprio PATH , por ex. execv .

Existem programas como kill , que estão disponíveis como um programa real e um shell integrado ao mesmo tempo. Se for esse o caso, preciso do caminho completo para o programa atual.

Existem vários utilitários que podem encontrar um programa no PATH , conforme especificado em Seção 2.9 .1.1, Busca de comando e Execução do padrão POSIX .

Existe which , que não faz parte de nenhum padrão. Pode ser um programa regular em alguns sistemas, enquanto alguns shells fornecem isso. Parece estar disponível na maioria dos sistemas e shells, mas os shells com uma versão embutida, também apenas retornam o nome do built-in em vez do caminho para o executável. Também não é padronizado de forma alguma e pode retornar qualquer saída e ter opções diferentes.

bash# which kill
/usr/bin/kill
dash# which kill
/usr/bin/kill
fish# which kill
/usr/bin/kill
mksh# which kill
/usr/bin/kill
tcsh# which kill
kill: shell built-in command.
zsh# which kill
kill: shell built-in command

Existe whence , que é um conjunto de alguns shells. Mas não está disponível em muitas conchas. Ele também retornará o nome do built-in em vez do caminho para o programa. Um -p pode ser passado para mudar esse comportamento.

bash# whence kill
bash: whence: command not found
dash# whence kill
dash: 1: whence: not found
fish# whence kill
fish: Unknown command 'whence'
mksh# whence kill
kill
mksh# whence -p kill
/usr/bin/kill
tcsh# whence kill
whence: Command not found.
zsh# whence kill
kill
zsh# whence -p kill
/usr/bin/kill

Existe o command construído especificado por POSIX: 2008 . Infelizmente ele também procura comandos e built-ins regulares e retornará o nome do built-in em vez do caminho para o programa sombreado por um built-in do mesmo nome. Alguns shells antigos ainda não implementaram.

bash# command -v kill
kill
dash# command -v kill
kill
fish# command -v kill
/usr/bin/kill
mksh# command -v kill
kill
tcsh# command -v kill
command: Command not found.
zsh# command -v kill
kill
    
por Sebastian Schrader 17.11.2016 / 15:46

1 resposta

11

Pesquise por você mesmo.

export IFS=":"
[ -z "${1}" ] && exit 1
for dir in $PATH
do
   if [ -x "${dir}/${1}" ];then
      echo "${dir}/${1}"
      exit 0
   fi
done
echo ${1} not found
exit 1

Testado em bash , dash , ksh , mksh , zsh

Atualizar

O acima é bom para um script autônomo, no entanto, se você está pensando em incorporar isso em um script maior, você pode querer usar algo mais parecido com o seguinte.

function find_path() {
   IFS_SAVE="${IFS}"
   export IFS=":"
   [ -z "${1}" ] && exit 1
   for dir in $PATH
   do
      if [ -x "${dir}/${1}" ];then
         echo "${dir}/${1}"
         export IFS="${IFS_SAVE}"
         return 0
      fi
   done
   export IFS="${IFS_SAVE}"
   echo ${1} not found
   return 1
}

Isso é para que IFS seja restaurado após encontrar a correspondência e também tenha trocado exit com return 's

    
por 17.11.2016 / 16:57

Tags