¿Por qué el mensaje de error para dos puntos como un comando (: :) en bash tiene tres puntos, pero un solo punto no da salida?


Respuestas:


40

El :shell incorporado frente a inexistente::

El : comando incorporado de shell existe (observe la diferencia entre los comandos externos e integrados ) que no hace nada; simplemente devuelve el éxito, al igual que el truecomando. El :incorporado es estándar y está definido por el estándar POSIX , donde también se conoce como la "utilidad nula". Se usa con frecuencia para probar o para ejecutar bucles infinitos como enwhile : ; do ...;done

bash-4.3$ type :
: is a shell builtin

Sin embargo, ::dos caracteres de dos puntos juntos se interpretan como una "palabra" para el shell, y se supone que es un comando que ingresó el usuario. El shell pasará por el proceso de verificación de las funciones integradas, luego cualquier directorio en la PATHvariable para la existencia de ese comando. Pero no hay un :: comando incorporado ni externo ::. Por lo tanto, eso produce un error.

Bueno, ¿cuál es un formato típico para un error?

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

Por lo tanto, lo que ves no son 3 puntos sino lo que escribiste pegado en el formato de error estándar.

Tenga en cuenta también que :puede tomar argumentos de línea de comandos, es decir, es legal hacerlo:

: :

En este caso, el shell considerará eso como dos "palabras", una de las cuales es un comando y la otra un parámetro posicional. ¡Eso tampoco producirá ningún error! (Consulte también la nota histórica (más adelante en esta respuesta) sobre el uso de los :parámetros posicionales).


En conchas que no sean bash

Tenga en cuenta que el formato también puede variar entre diferentes shells. Para bash, kshy mkshel comportamiento es consistente. Por ejemplo, el /bin/shshell predeterminado de Ubuntu (que en realidad es /bin/dash):

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

donde 1 es el número de comando (equivalente al número de línea en un script).

csh por el contrario no produce ningún mensaje de error:

$ csh
% ::
%

De hecho, si ejecuta strace -o csh.trace csh -c ::, la salida de rastreo en el csh.tracearchivo revela que cshsale con el estado de salida 0 (sin errores). Pero tcshgenera el error (sin generar su nombre):

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

Error de mensajes

En general, el primer elemento en el mensaje de error debe ser el proceso o la función de ejecución (su shell intenta ejecutarse ::, por lo tanto, el mensaje de error proviene del shell). Por ejemplo, aquí el proceso de ejecución es stat:

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

De hecho, POSIX define la función perror () , que de acuerdo con la documentación toma un argumento de cadena, luego emite un mensaje de error después de dos puntos y luego una nueva línea. Citar:

La función perror () asignará el número de error al que se accede a través del símbolo errno a un mensaje de error dependiente del idioma, que se escribirá en el flujo de error estándar de la siguiente manera:

  • Primero (si s no es un puntero nulo y el carácter al que apunta s no es el byte nulo), la cadena a la que apunta s seguido de dos puntos y un <space>.

  • Luego aparece una cadena de mensaje de error seguida de una <línea nueva>.

Y el argumento de cadena para perror()técnicamente podría ser cualquier cosa, pero, por supuesto, para mayor claridad, generalmente es el nombre de la función o argv[0].

Por el contrario, GNU tiene su propio conjunto de funciones y variables para el manejo de errores , que un programador puede usar fprintf()para stderrtransmitir. Como muestra uno de los ejemplos en la página vinculada, se podría hacer algo como esto:

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

Nota historica

En el antiguo shell de Unix y Thompson, :se usaba con una gotodeclaración (que según el usuario llamado Perderabo en este hilo no era un shell incorporado). Cita del manual:

Se busca en el archivo de comando completo una línea que comience con: como el primer carácter no en blanco, seguido de uno o más espacios en blanco y luego la etiqueta. Si se encuentra dicha línea, goto reposiciona el desplazamiento del archivo de comando a la línea después de la etiqueta y sale. Esto hace que el shell se transfiera a la línea etiquetada.

Entonces, podría hacer algo como esto para hacer un script de bucle infinito:

: repeat
echo "Hello World"
goto repeat


1
DOS command.comy Windows cmd.exetienen una situación similar pero opuesta: :es explícitamente una etiqueta de goto (no un comando) y a menudo se reutiliza como un carácter de comentario (por ejemplo :: This is a comment).
Grawity

54

Los dos puntos finales son solo parte del mensaje predeterminado "no encontrado":

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

La razón por la que un solo colon no produce nada es que : es un comando válido, aunque no hace nada (excepto el retorno TRUE). De la SHELL BUILTIN COMMANDSsección de man bash:

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

A veces lo verás en construcciones como

while :
do
  something
done

Ver por ejemplo ¿ Para qué sirve el colon incorporado?


sí, este es el comentario más completo ... mucho más elocuente que el mío ... mucho mejor explicado: D
John Orion

8

Pruebe cualquier otro comando inexistente y verá que :cumple su propósito normal en inglés:

$ ---
---: command not found

6

Los dos puntos añadidos son parte del mensaje de error en sí. Si uno teclea cd ow, da como resultado bash: cd: ow: No such file or directory, lo que muestra que el error está poniendo el colon extra: No such file or directory


6
$ ::
bash: ::: command not found
$ kkkk
bash: kkkk: command not found

el tercero es un espaciador del formateo

en bash a :es una instrucción vacía de línea vacía


4

obtienes 3 puntos porque el formato de error contiene dos puntos:

bash: <command>: command not found
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.