Como distinguir entre util interna e externa? (por exemplo, eco)

3

Alguns comandos são fornecidos como builtins e utilitários externos. Tome echo por exemplo. Na minha máquina (macOS) rodando o Bash 3.2,

$ type echo
echo is a shell builtin

A execução de man bash | less --pattern='^ *echo +\[' mostra:

echo [-neE] [arg ...]

Mas a execução de man 1 echo mostra uma página man para uma implementação diferente de echo , com uma assinatura diferente:

echo [-n] [string ...]

Consigo usar -e com êxito, por isso devo estar executando o arquivo incorporado e, presumivelmente, /bin/echo

$ which echo
/bin/echo

Onde a outra implementação está ativa e como posso distinguir entre builtins e utils externos em geral (por exemplo, printf )

Atualização / Correção Obrigado @Gilles por esclarecer. E a prova está no pudim!

$ /bin/echo -e "\tabc"
-e \tabc

$ echo -e "\tabc"
        abc
    
por ivan 18.06.2017 / 00:32

2 respostas

8

Para descobrir se um comando está embutido, execute type .

$ type echo
echo is a shell builtin

type é em si um builtin e sabe quais comandos são construídos. (No bash, builtins podem ser desabilitados, e type informará corretamente que um comando não está embutido se o builtin tiver sido desabilitado). type relata o que será executado se você usar o nome do comando - alias, função, comando interno ou externo.

which é um comando externo que informa a localização de comandos externos. Não sabe nada sobre aliases, funções ou builtins. E pode até não informar os comandos externos corretos, dependendo da sua configuração. Apenas esqueça sobre which e use type .

I must be running the builtin, and presumably that's /bin/echo

Não! Por definição, um builtin não é um comando externo. O código que implementa o echo incorporado, como todos os outros recursos internos, está em /bin/bash . /bin/echo é um comando externo com o mesmo nome que o echo construído.

Quando um comando existe como um comando interno e externo, usar seu nome chama o interno. A ordem de precedência para nomes de comandos é alias, depois function, then builtin e, em seguida, comando externo nos diretórios listados em $PATH em ordem. Se, por algum motivo, você quiser forçar um comando externo, use o caminho completo.

    
por 18.06.2017 / 00:47
2

nome conhecido (palavra)

A melhor maneira de encontrar o que fornece um word (desde que a palavra seja um nome válido para um apelido, função ou comando) é usar a opção -a to type :

$ type -a echo
echo is a shell builtin
echo is /bin/echo

Se uma função e um alias também forem definidos, você poderá obter uma lista semelhante a esta:

$ type -a echo
echo is aliased to 'echo "A new echo"'
echo is a function
echo ()
{
    printf '%s\n' "A function echo" "$@"
}
echo is a shell builtin
echo is /bin/echo

A ordem em que eles são impressos é a ordem de prioridade. Na lista impressa acima: o alias será executado primeiro. Se o alias for removido ( unalias ), a função será executada. E assim por diante e assim por diante.

Exemplo:

$ echo "test"
A function echo
A new echo
test

As citações normalmente ignoram aliases:

$ \echo         # or "e"cho, "echo", 'e'"ch"o, and many other variations.
A function echo
test

Qual é o mesmo que desabilitar o alias:

$ unalias echo; echo test
A function echo
test

A função pode ser apagada com unset (opção -f):

$ unset -f echo 
$ type -a echo
echo is a shell builtin
echo is /bin/echo

Um alias pode ser desativado com a ativação:

$ enable -n echo
$ type -a echo
echo is /bin/echo

E um utilitário externo (externo ao shell) pode ser movido:

# mv /bin/echo /bin/echo-aside
# type -a echo
bash: type: echo: not found

Uma lista de builtins

Se o nome do builtin não for conhecido, ele poderá ser listado.

No bash, há um comando (talvez?) chamado estranhamente chamado enable ( builtin in ksh ).
Chamar enable sem opção imprimirá uma lista enabled de builtins:

$ enable
enable .
enable :
enable [
enable alias
…

Existem opções para imprimir todas ( -a ), apenas ativadas ( -p ou nada) e especiais (conforme definidas por Posix) ( -s ).

Removendo a palavra enable e tornando-a uma lista de uma linha:

$ echo $(enable -s | cut -d" " -f2)
. : break continue eval exec exit export readonly return set shift source times trap unset

$ echo $(enable -p | cut -d" " -f2)
. : [ alias bg bind break builtin caller cd command compgen complete compopt continue declare dirs disown echo enable eval exec exit export false fc fg getopts hash help history jobs kill let local logout mapfile popd printf pushd pwd read readarray readonly return set shift shopt source suspend test times trap true type typeset ulimit umask unalias unset wait
    
por 18.06.2017 / 03:48