Ordem dos executáveis ​​iniciados no bash

14

Se eu executar o testcomando no bash, o testutilitário interno (avalia expressão condicional) é iniciado:

$ type test
test is a shell builtin
$ type -a test
test is a shell builtin
test is /usr/local/bin/test
test is /usr/bin/test
$ 

No entanto, como visto na saída type -a testacima, existe outro testdiretório / usr / local / bin e outro diretório / usr / bin. Como os executáveis ​​são ordenados, ou seja, os comandos internos são sempre preferidos e o restante dos comandos depende da ordem do diretório na variável $ PATH? Além disso, é possível alterar a ordem dos executáveis ​​iniciados, por exemplo, se eu digitar test, / usr / bin / test será iniciado em vez do bash-builtin test?

Martin
fonte
Você pode especificar o caminho completo ao chamar o comando, por exemplo, /usr/bin/test -f "$file"...
jasonwryan
@jasonwryan Estou ciente disso, mas estou interessado apenas se houver uma maneira de alterar a ordem dos executáveis ​​iniciados.
Martin

Respostas:

25

A prioridade mais alta é o alias do bash, depois os embutidos especiais (apenas no modo POSIX), depois as funções, os embutidos e, em seguida, uma pesquisa $PATH.

Para executar um builtin, use builtin test.
Para executar uma aplicação externa, use um caminho explícito: /bin/test.
Para ignorar funções e aliases, use command test.
Para ignorar apenas alias, use \testou qualquer outro tipo de expansão.

É possível desativar / ativar um builtin com enable test.

(Atualizado de acordo com os comentários abaixo)
(Corrigida a edição incorreta do administrador que o bash havia disableincorporado - na verdade, existe apenas enable)

gena2x
fonte
1
@ 1_CR gena2x está certo. Minha resposta omitiu os buildins especiais, que têm precedência sobre as funções conforme POSIX (embora alguns shells não sejam compatíveis; o bash é compatível apenas no modo POSIX).
Gilles 'SO- stop be evil'
1
Edição sugerida: os aliases são desativados quando você cita o comando (ou qualquer parte dele), como em \testou 'test'ou tes't'.
John Kugelman
2
Isso não é imagem completa. Parece que qualquer tipo de expansão (no manual do bash, toda a substituição, expansão de til e assim por diante chamada expansão ) desativa os aliases. Eu tentei.
Gena2x
1
Citar a partir da página man bash:.. "A primeira palavra de cada comando simples, se não cotados, é verificado para ver se ele tem um alias Se assim for, essa palavra é substituído pelo texto do alias Os personagens /, $, crase, e =e qualquer um dos metacaracteres do shell ou caracteres de citação listados acima pode não aparecer em um nome alternativo ".
John Kugelman
2
+1 para obter dicas para me ajudar a encontrar a fonte dessas informações: está na página de manual do bash, na seção EXECUÇÃO DE COMANDO, segundo e terceiro parágrafos.
precisa
6

Os comandos internos são sempre preferidos aos comandos externos. A lógica é que o comando interno é mais rápido (e, em alguns casos, como cdou , apenas o comando interno pode ter o efeito desejado).test -o BASH_OPTION

Às vezes, o comando externo pode ter recursos que o shell interno não possui. Nesse caso, você pode chamar o comando externo, fornecendo um caminho explícito (ou seja, contendo uma barra) (isso ignora qualquer preocupação com a ordem em $PATH). Se você não deseja codificar o caminho externo, mas deseja impedir o uso do built-in, use "$(type -P test)"(note capital P) no bash, "$(whence -p test)"no ksh e =testno zsh. Outra maneira de forçar o uso de um comando externo é usar o commandbuiltin ( command -p test …) ou passar pelo envutilitário ( env test …).

No zsh, você pode desativar um builtin com disable test. Isso é permanente (para o shell ou subshell atual) até que o builtin seja reativado enable test. No bash, você pode fazer o mesmo com enable -n testpara desativar e enable testreativar.

Você pode usar um alias ou função para forçar a execução de um comando diferente, por exemplo alias test=/usr/bin/testou test () { /usr/bin/test "$@"; }. Se você tiver esse apelido, poderá impedir seu uso citando qualquer parte dele, por exemplo \test, executará a função normal / pesquisa interna / externa. Observe que, dependendo do shell e de suas configurações, as definições de alias em uma função podem ser expandidas quando uma função é lida ou quando é executada. Se você definiu uma função, pode command testevitar a pesquisa de funções, bem como a pesquisa de alias (portanto, aqui o testbuiltin será chamado, a menos que seja desativado).

Gilles 'SO- parar de ser mau'
fonte
não envseria apropriado aqui também?
Steven Penny
então, se o shell é executado no BusyBox, existem outros comandos, geralmente externos do mesmo BusyBox, considerados internos? por exemplo, adicionei full dfa um PATH na primeira posição, removi o apelido 'df', which dfmostra / opt / bin / df, mas o df roda / bin / df -> busybox
papo
O @papo which dfnão mostra necessariamente o que dfé executado. unix.stackexchange.com/questions/85249/…
Gilles 'SO- stop