Por que a mensagem de erro para dois dois pontos como um comando (: :) no bash possui três dois pontos, mas um único ponto não fornece saída?

27

Se eu digitar

::

em um shell bash, recebo:

-bash: ::: command not found

Mas, apenas um :resulta em nenhuma saída. Por que é isso?

NerdOfLinux
fonte
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Thomas Ward
Como isso está relacionado ao Ubuntu?
NerdOfCode
@NerdOfCode da mesma maneira que é? meta.askubuntu.com/q/17076/158442
muru

Respostas:

40

O :shell embutido vs inexistente::

O : comando interno do shell existe (observe a diferença entre comandos externos e internos ) que não faz nada; apenas retorna sucesso, assim como o truecomando. O :built-in é padrão e definido pelo padrão POSIX , onde também é conhecido como "utilitário nulo". É freqüentemente usado para testar ou executar loops infinitos, como emwhile : ; do ...;done

bash-4.3$ type :
: is a shell builtin

No entanto, ::- dois caracteres de dois pontos juntos - são interpretados como uma "palavra" no shell e supõe ser um comando digitado pelo usuário. O shell passará pelo processo de verificação de built-ins e, em seguida, qualquer diretório na PATHvariável para a existência desse comando. Mas não existe um :: comando interno nem externo ::. Portanto, isso produz um erro.

Bem, qual é o formato típico para um erro?

<shell>: <command user typed>: error message

Portanto, o que você vê não são três pontos, mas o que você digitou colou no formato de erro padrão.

Observe também que isso :pode receber argumentos de linha de comando, ou seja, é legal fazer:

: :

Nesse caso, o shell considerará isso como duas "palavras", uma das quais é um comando e a outra um parâmetro posicional. Isso também não produzirá nenhum erro! (Veja também a nota histórica (mais adiante nesta resposta) sobre o uso de :com parâmetros posicionais.)


Em conchas que não sejam bash

Observe que a formatação também pode variar entre diferentes shells. Para bash,, kshe mksho comportamento é consistente. Por exemplo, o /bin/shshell padrão do Ubuntu (que é realmente /bin/dash):

$ dash
$ ::
dash: 1: ::: not found

onde 1 é o número do comando (equivalente ao número da linha em um script).

csh por outro lado, não produz nenhuma mensagem de erro:

$ csh
% ::
%

De fato, se você executar strace -o csh.trace csh -c ::, a saída de rastreamento no csh.tracearquivo revela que cshsai com o status de saída 0 (sem erros). Mas tcshgera o erro (sem exibir seu nome):

$ tcsh
localhost:~> ::
::: Command not found.

Mensagens de erro

Em geral, o primeiro item na mensagem de erro deve ser o processo ou função em execução (seu shell tenta executar ::, portanto, a mensagem de erro vem do shell). Por exemplo, aqui o processo de execução é stat:

$ stat noexist
stat: cannot stat 'noexist': No such file or directory

De fato, o POSIX define a função perror () , que, de acordo com a documentação, utiliza um argumento de seqüência de caracteres, emite uma mensagem de erro após dois pontos e, em seguida, nova linha. Citar:

A função perror () deve mapear o número do erro acessado através do símbolo errno para uma mensagem de erro dependente do idioma, que deve ser gravada no fluxo de erros padrão da seguinte maneira:

  • Primeiro (se s não for um ponteiro nulo e o caractere apontado por s não for o byte nulo), a cadeia de caracteres apontada por s seguida por dois pontos e um <espaço>.

  • Em seguida, uma sequência de mensagens de erro seguida por um <newline>.

E o argumento da cadeia de caracteres para perror()tecnicamente pode ser qualquer coisa, mas é claro, para maior clareza, normalmente é o nome da função ou argv[0].

Por outro lado, o GNU possui seu próprio conjunto de funções e variáveis ​​para tratamento de erros , com as quais um programador pode usar fprintf()para stderrtransmitir. Como mostra um dos exemplos na página vinculada, algo como isto pode ser feito:

  fprintf (stderr, "%s: Couldn't open file %s; %s\n",
           program_invocation_short_name, name, strerror (errno));

Nota histórica

No antigo Unix e Thompson, o shell :era usado com a gotoinstrução (que, de acordo com o usuário chamado Perderabo neste segmento, não era um shell interno ). Citação do manual:

O arquivo de comando inteiro é procurado por uma linha que começa com a: como o primeiro caractere não em branco, seguido por um ou mais espaços em branco e, em seguida, o rótulo. Se essa linha for encontrada, goto reposiciona o deslocamento do arquivo de comando para a linha após o rótulo e sai. Isso faz com que o shell seja transferido para a linha rotulada.

Então você pode fazer algo assim para criar um script de loop infinito:

: repeat
echo "Hello World"
goto repeat
Sergiy Kolodyazhnyy
fonte
Erro de
1
O DOS command.come o Windows ' cmd.exetêm uma situação semelhante, mas oposta: :é explicitamente um rótulo de goto (não um comando) e é frequentemente redirecionado como um caractere de comentário (por exemplo :: This is a comment).
grawity
54

Os últimos dois pontos são apenas parte da mensagem padrão "não encontrado":

$ x
x: command not found
$ ::
::: command not found

A razão pela qual um único dois pontos não produz nada é que : é um comando válido - embora não faça nada (exceto retornar TRUE). Na SHELL BUILTIN COMMANDSseção de man bash:

   : [arguments]
          No effect; the command does nothing beyond  expanding  arguments
          and  performing any specified redirections.  A zero exit code is
          returned.

Você às vezes verá isso em construções como

while :
do
  something
done

Veja, por exemplo, a que finalidade serve o cólon incorporado?

chave de aço
fonte
sim este é o mais abrangente comentário .. muito mais eloquente do que a minha .. muito melhor explicou: D
John Orion
8

Tente qualquer outro comando inexistente e você verá que isso :serve a seu propósito normal em inglês:

$ ---
---: command not found
Olorin
fonte
6

Os dois pontos adicionados fazem parte da própria mensagem de erro. Se alguém digitar cd owisso resulta bash: cd: ow: No such file or directory, o que mostra que o erro está colocando dois pontos extras: No such file or directory

John Orion
fonte
6
$ ::
bash: ::: command not found
$ kkkk
bash: kkkk: command not found

o terceiro é um espaçador da formatação

no bash a :é uma instrução de linha vazia

user688056
fonte
4

você recebe três pontos, porque o formato do erro contém dois pontos:

bash: <command>: command not found
ravery
fonte