Pourquoi le message d'erreur pour deux deux-points en tant que commande (: :) dans bash a trois deux-points, mais un seul deux-points ne donne aucune sortie?

27

Si je tape

::

dans un shell bash, j'obtiens:

-bash: ::: command not found

Mais, un seul ne :génère aucune sortie. Pourquoi est-ce?

NerdOfLinux
la source
Les commentaires ne sont pas pour une discussion approfondie; cette conversation a été déplacée vers le chat .
Thomas Ward
Quel est le lien avec Ubuntu?
NerdOfCode
@NerdOfCode de la même manière? meta.askubuntu.com/q/17076/158442
muru

Réponses:

40

Le :shell intégré vs inexistant::

La : commande intégrée du shell existe (notez la différence entre les commandes externes et intégrées ) qui ne fait rien; il renvoie juste le succès, tout comme la truecommande. La fonction :intégrée est standard et définie par la norme POSIX , où elle est également connue sous le nom d '"utilitaire nul". Il est fréquemment utilisé pour tester ou exécuter des boucles infinies comme danswhile : ; do ...;done

bash-4.3$ type :
: is a shell builtin

Cependant, ::- deux deux points ensemble - sont interprétés comme un "mot" pour le shell, et cela suppose que c'est une commande que l'utilisateur a entrée. Le shell passera par le processus de vérification des intégrés, puis n'importe quel répertoire de la PATHvariable pour l'existence de cette commande. Mais il n'y a ni commande intégrée :: ni commande externe ::. Par conséquent, cela produit une erreur.

Eh bien, quel est le format typique d'une erreur?

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

Ainsi, ce que vous voyez n'est pas 3 colons mais ce que vous avez tapé collé dans le format d'erreur standard.

Notez également que cela :peut prendre des arguments en ligne de commande, c'est-à-dire qu'il est légal de le faire:

: :

Dans ce cas, le shell considérera cela comme deux "mots", dont l'un est une commande et l'autre un paramètre positionnel. Cela ne produira également aucune erreur! (Voir également la note historique (plus loin dans cette réponse) sur l'utilisation de of :avec des paramètres positionnels.)


En coquilles autres que bash

Notez que le formatage peut également varier entre différents shells. Pour bash, kshet mkshle comportement est cohérent. Par exemple, le /bin/shshell par défaut d'Ubuntu (qui est en fait /bin/dash):

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

où 1 est le numéro de commande (équivalent au numéro de ligne dans un script).

csh en revanche, ne produit aucun message d'erreur:

$ csh
% ::
%

En fait, si vous exécutez strace -o csh.trace csh -c ::, la sortie de trace dans le csh.tracefichier révèle que les cshsorties avec le statut de sortie 0 (aucune erreur). Mais tcshgénère l'erreur (sans sortir son nom, cependant):

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

Messages d'erreur

En général, le premier élément du message d'erreur doit être le processus ou la fonction d'exécution (votre shell essaie de s'exécuter ::, d'où le message d'erreur vient du shell). Par exemple, voici le processus d'exécution stat:

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

En fait, POSIX définit la fonction perror () qui, selon la documentation, prend un argument de chaîne, puis génère un message d'erreur après deux-points, puis une nouvelle ligne. Citation:

La fonction perror () doit mapper le numéro d'erreur accessible via le symbole errno à un message d'erreur dépendant de la langue, qui doit être écrit dans le flux d'erreur standard comme suit:

  • Tout d'abord (si s n'est pas un pointeur nul et que le caractère pointé par s n'est pas l'octet nul), la chaîne pointée par s suivie d'un deux-points et d'un <espace>.

  • Ensuite, une chaîne de message d'erreur suivie d'un <newline>.

Et l'argument chaîne à perror()techniquement pourrait être n'importe quoi, mais bien sûr, pour plus de clarté, c'est généralement le nom de la fonction ou argv[0].

En revanche, GNU possède son propre ensemble de fonctions et de variables pour la gestion des erreurs , qu'un programmeur peut utiliser fprintf()pour stderrdiffuser. Comme le montre l'un des exemples de la page liée, quelque chose comme cela pourrait être fait:

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

Note historique

Dans l'ancien shell Unix et Thompson, :était utilisé avec l' gotoinstruction (qui, selon l'utilisateur nommé Perderabo sur ce thread, n'était pas un shell intégré). Citation du manuel:

L'ensemble du fichier de commandes est recherché pour une ligne commençant par a: comme premier caractère non vide, suivi par un ou plusieurs blancs, puis l'étiquette. Si une telle ligne est trouvée, goto repositionne le décalage du fichier de commandes sur la ligne après l'étiquette et quitte. Cela provoque le shell à transférer vers la ligne étiquetée.

Vous pouvez donc faire quelque chose comme ça pour créer un script de boucle infinie:

: repeat
echo "Hello World"
goto repeat
Sergiy Kolodyazhnyy
la source
Typo
1
DOS command.comet Windows cmd.exeont une situation similaire mais opposée: :est explicitement une étiquette goto (pas une commande) et souvent réutilisée comme un caractère de commentaire (par exemple :: This is a comment).
grawity
54

Le dernier deux-points n'est qu'une partie du message par défaut "introuvable":

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

La raison pour laquelle un seul deux-points ne produit rien est qu'il : s'agit d' une commande valide - bien qu'elle ne fasse rien (sauf retour TRUE). De la SHELL BUILTIN COMMANDSsection de man bash:

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

Vous le verrez parfois dans des constructions comme

while :
do
  something
done

Voir par exemple À quoi sert la fonction intégrée du côlon?

tournevis
la source
ouais c'est le commentaire le plus complet .. beaucoup plus éloquent que le mien .. beaucoup mieux expliqué: D
John Orion
8

Essayez n'importe quelle autre commande inexistante et vous verrez que le :sert son objectif normal en anglais:

$ ---
---: command not found
Olorin
la source
6

Les deux points ajoutés font partie du message d'erreur lui-même. Si l'on tape, cd owil en résulte bash: cd: ow: No such file or directory, ce qui montre que l'erreur met les deux points supplémentaires: No such file or directory

John Orion
la source
6
$ ::
bash: ::: command not found
$ kkkk
bash: kkkk: command not found

le 3ème est un espaceur de formatage

dans bash a :est une instruction vide de ligne vide

user688056
la source
4

vous obtenez 3 deux points car le format d'erreur contient deux points:

bash: <command>: command not found
délire
la source