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 exec*
funções que não pesquisa por PATH
si só, por exemplo execv
.
Existem programas como o kill
que estão disponíveis como um programa real e um shell embutido ao mesmo tempo. Se for esse o caso, preciso do caminho completo para o programa real.
Existem vários utilitários que podem encontrar um programa PATH
conforme especificado na Seção 2.9.1.1, Pesquisa de comando e execução do padrão POSIX .
Existe which
, o que não faz parte de nenhum padrão. Pode ser um programa regular em alguns sistemas, enquanto alguns shells fornecem que é um componente interno. Parece estar disponível na maioria dos sistemas e shells, mas os shells com uma versão interna também retornam apenas 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 built-in de algumas conchas. Mas não está disponível em muitas conchas. Também retornará o nome do built-in em vez do caminho para o programa. A -p
pode ser passado para onde alterar 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
built-in especificado por POSIX: 2008 . Infelizmente, ele também procura comandos regulares e embutidos e retornará o nome do embutido em vez do caminho para o programa sombreado por um embutido com o mesmo nome. Algumas conchas antigas ainda não foram implementadas.
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
enable
está especificado no POSIX ou não, mas se estiver, você pode usarenable -n which
para desativar o shell interno dowhich
.realpath
enable
é fornecido apenas porbash
ezsh
type -p
. Tanto o bash quanto o dash permitem dizer ocommand
comando para executar um executável real, mesmo se houver uma função ou um builtin com o mesmo nome.command
ignora funções (e aliases), mas NÃO está embutido, como o Q diz corretamente. E você nem sempre pode usar um shebang porque não há caminho que obtenha um shell específico, ou mesmo algum shell POSIX, em todos os sistemas.Respostas:
Basta procurar por si mesmo.
Testado em
bash
,dash
,ksh
,mksh
,zsh
Atualizar
O acima é bom para um script independente, no entanto, se você planeja incorporá-lo a um script maior, pode usar algo mais parecido com o seguinte.
Isso é para que
IFS
é restaurada depois de encontrar o jogo, também trocadasexit
's comreturn
' sfonte
IFS
variável? Não é suficiente ter esse conjunto no shell local? Falando em local, serialocal IFS
portátil? O acima pode interagir mal se algo estiver salvando o IFS da mesma maneira. Olhando para esta pergunta no SE ,local
pode funcionar para a maioria dos shells, apesar de não ser POSIX. Colocar a versão original em um(…)
subshell também pode funcionar.