Por que existe um / bin / echo e por que eu gostaria de usá-lo?

52

Notei que há um executável binário /bin/echono meu sistema Ubuntu MATE 17.04.

Eu pensei, isso é estranho, porque

$ type echo
echo is a shell builtin

O teste superficial sugere que /bin/echofaz o mesmo tipo de coisa que o Bash embutido echo:

$ /bin/echo foo
foo
$ /bin/echo $USER
zanna

Então, por que há outra versão echoseparada do programa Bash e por que ou quando eu gostaria de usá-lo?

Zanna
fonte
2
@ bodhi.zazen Isso é bastante útil, mesmo que não seja o mesmo, porque aborda o inverso dessa pergunta. Essa pergunta pergunta por que echoé fornecida como um shell embutido, enquanto essa pergunta por que é fornecida como um comando externo.
Eliah Kagan 30/09
3
Uma razão é que nem todo mundo usa o bash. Eu acho que / bin / echo é anterior ao bash, e os desenvolvedores acharam útil / eficiente incluí-lo como um built-in em vez de usar o executável.
jamesqf

Respostas:

87

Se você abrir um bashprompt e digitar um echocomando, ele utilizará um shell embutido em vez de executar /bin/echo. As razões pelas quais ainda é importante /bin/echoexistir são:

  1. Você não está sempre usando um shell. Em várias circunstâncias, você executa um executável diretamente e não através de um shell.
  2. Pelo menos em teoria, algumas conchas não têm um echointerior. Isso não é realmente necessário.

Para expandir o número 1, suponha que você deseje mover todos os arquivos regulares cujos nomes começaram com abcqualquer lugar srcpara dest. Existem várias maneiras de fazer isso, mas uma delas é:

find src -name 'abc*' -type f -exec mv -nv {} dest/ \;

Mas suponha que, em vez de apenas executá-lo, você queira ver todos os comandos que serão executados primeiro. Bem, você pode anexar echoao comando da mesma maneira que em outros contextos:

find src -name 'abc*' -type f -exec echo mv -nv {} dest/ \;

Mas findnão usa um shell. Isso corre /bin/echo.

Além de findcom -execou-execdir , o /bin/echoexecutável será chamado por outros programas que se executam programas, mas não através de um shell. Isso acontece com o xargscomando (que está relacionado a find), bem como em vários outros contextos, tais como a Exec=linha de um .desktoparquivo . Outro exemplo é quando você executa sudo echo, o que pode ser útil para testar se sudoestá funcionando.

Da mesma forma, algumas conchas têm um printfbuiltin, mas /usr/bin/printftambém existe.

Uma razão possível menos comum que você pode usar deliberadamente /bin/echoé se estiver contando com as diferenças entre ela e o echocomando fornecido pelo seu shell. man echodocumentos /bin/echo; help echoem bash documentos do bashbuiltin. echonão é muito portátil, porque implementações diferentes - tanto em sistemas operacionais quanto em shells no mesmo sistema operacional - suportam opções diferentes (por exemplo, -e) e diferem no tratamento de barras invertidas . Obviamente, é melhor evitar confiar nesses detalhes e usá-lo printf, o que é muito mais portátil .

Em bash, você pode fazer o typeshow embutido /bin/echotambém - assumindo que /binestá no seu $PATHcomo sempre deveria ser - passando a -abandeira :

$ type -a echo
echo is a shell builtin
echo is /bin/echo
Eliah Kagan
fonte
21
E também porque a especificação POSIX diz que deve haver uma.
Glenn Jackman
4
@glennjackman Eu esperava que alguém postasse uma resposta sobre isso, na verdade, e espero que você decida fazer isso! Há alguma sutileza envolvida, porém, já que nem o Debian, o Ubuntu nem o GNU Coreutils (nem o Projeto GNU em geral) tentam cumprir o POSIX em tudo . Por exemplo, o POSIX insiste na cdexistência de um executável (que, quando executado, altera o diretório e sai, deixando o chamador onde estava antes) e alguns SOs possuem um. Pode ser útil citar 4.1 nos padrões GNU .
Eliah Kagan 30/09
@EliahKagan: Aliás, / usr / bin / cd tem um uso: / usr / bin / cd O comando directory executa esse comando nesse diretório. Se a alteração do diretório falhar, o comando não será iniciado.
Josué
4
@ Josuéa uma melhor utilização cdé simplesmente como um teste de capacidade de acessar um determinado diretório: se /usr/bin/cd some/dirfor bem-sucedido, em uma tentativa você testou: a) que some/direxiste, b) que é um diretório ou um link para um ec) existem permissões necessárias para você acessar esse diretório; tudo sem mudar seu próprio estado.
1/17
11
@CarlWitthoft, consulte Por que printf é melhor que eco? Além disso /bin/echo, não é \bin\echo, a menos que você esteja usando o Windows. ;)
Curinga
31

Eliah fez um ótimo trabalho em responder a isso, mas quero comentar sobre a parte "por que há outra versão do echoprograma Bash separado"? Essa é a pergunta errada.

A pergunta certa é: por que isso é embutido em primeiro lugar , quando poderia ter sido (e é) um comando externo perfeitamente adequado?

Por uma questão de simplicidade, dê uma olhada nos builtins no dash, um mísero 38 (o bash tem 61, para comparação, seguindo a saída de compgen -b):

.               continue        getopts         readonly        type
:               echo            hash            return          ulimit
[               eval            jobs            set             umask
alias           exec            kill            shift           unalias
bg              exit            local           test            unset
break           export          printf          times           wait
cd              false           pwd             trap
command         fg              read            true

Quantos destes precisam ser construídos? [, echo, false, printf, pwd, test, E truenão precisa ser builtins: Eles não fazem nada que só um builtin pode fazer (afectam ou obter estado shell que não está disponível para comandos externos). O Bash's, printfpelo menos, tira vantagem de ser um builtin: printf -v varsalva a saída na variável var. timeO bash também é especial: sendo uma palavra-chave, você pode cronometrar listas de comandos arbitrárias no bash (o dash não tem um timeequivalente). pwdtambém não precisa ser incorporado - qualquer comando externo herdará o diretório de trabalho atual (e também é um comando externo ).:é uma exceção - você precisa de um NOP, e :é isso. O restante executa ações que um comando externo pode executar facilmente.

Portanto, um quinto desses componentes não precisa ser construído. Porquê então? A página de dashmanual * na verdade explica de passagem por que esses recursos estão embutidos (ênfase minha):

Builtins
 Esta seção lista os comandos internos que estão embutidos porque eles
 precisa executar alguma operação que não possa ser executada por um
 processo. Além desses, existem vários outros comandos que podem
 ser construído para eficiência (por exemplo, printf (1), eco (1), teste (1), etc.).

É praticamente isso: esses built-in estão lá porque são usados ​​com frequência, de forma interativa e em scripts, e sua funcionalidade é simples o suficiente para que o shell possa fazer o trabalho. E assim acontece: algumas conchas (a maioria?) Assumiram o cargo. ** Volte para ash partir do 2,9 BSD e você não encontrará um echobuiltin.

Portanto, é perfeitamente possível que um shell mínimo possa pular a implementação de comandos como builtins (acho que nenhum shell atual o faz). O projeto coreutils do GNU não pressupõe que você os execute em um shell específico, e o POSIX requer esses comandos. Portanto, o coreutils os fornece de qualquer maneira e ignora aqueles que não têm nenhum significado fora do shell.


* Isso é quase idêntico ao texto da página de manual correspondente do shell Almquist , no qual o dash, o shell Debian Almquist, é baseado.

** zshleva essa idéia ao extremo: os comandos que você obtém ao carregar vários módulos, como zmv, são coisas que você não acha que um shell precisa entrar . Nesse ponto, a verdadeira questão é: por que você usaria o bash em vez do zsh, que possui todos esses recursos?

muru
fonte
11
Acontece que: também não precisa ser incorporado. É simplesmente bobo não ser um builtin. A menos que você esteja lidando com problemas iniciais no nível de inicialização do disquete de recuperação (nesse caso, eu descobri da maneira mais difícil que o pwd também não funciona de maneira confiável), a única penalidade por não ter isso como interno é um desempenho terrível.
Joshua
5
@ Josué não, :como um externo não seria realmente um NOP, você ainda teria uma PATHpesquisa, uma tentativa de executar o comando etc., quando tudo que você realmente deseja é não fazer nada expressamente. :como um builtin faz isso.
Muru
2
O Bash realmente precisa pwdser incorporado para funcionar da maneira que funciona, com o comportamento padrão de mostrar o caminho "lógico" ( pwd -L). /bin/pwdsó poderia implementar o pwd -Pcomportamento de mostrar os diretórios pai reais, não o link simbólico que você cdeditou.
Peter Cordes
2
@PeterCordes pwdestado 's é um pouco comprometida pela presença de PWD, mas sim, que é também um exemplo de festa utilizando o estado incorporado para melhorar a funcionalidade
Muni