Ubuntu: Why does the error message for two colons as a command (::) in bash have three colons, but a single colon give no output?



Question:

If I type

::  

into a bash shell, I get:

-bash: ::: command not found  

But, only one : results in no output. Why is this?


Solution:1

The : shell built-in vs non-existent ::

The : shell built-in command exists (note the difference between external and built-in commands) which does nothing; it just returns success, just like the true command. The : built-in is standard and defined by the POSIX standard, where it's also known as the "null utility". It is frequently used for testing or for running infinite loops as in while : ; do ...;done

bash-4.3$ type :  : is a shell builtin  

However, :: - two colon characters together - are interpreted as one "word" to the shell, and it assumes to be a command the user entered. The shell will go through the process of checking built-ins, then any directory in the PATH variable for existence of that command. But there is neither a built-in :: nor external command ::. Therefore, that produces an error.

Well, what is a typical format for an error?

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

Thus, what you see isn't 3 colons but what you typed pasted into the standard error format.

Note also, that : can take command-line arguments, i.e. it is legal to do:

: :  

In this case, the shell will consider that as two "words", one of which is a command and the other a positional parameter. That will also produce no error! (See also the historical note (later in this answer) about the use the of : with positional parameters.)


In shells other than bash

Note that formatting can vary between different shells as well. For bash, ksh, and mksh the behavior is consistent. For instance, Ubuntu's default /bin/sh shell (which is actually /bin/dash):

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

where 1 is the command number (equivalent to the line number in a script).

csh by contrast produces no error message at all:

$ csh  % ::  %  

In fact, if you run strace -o csh.trace csh -c ::, the trace output in csh.trace file reveals that csh exits with exit status 0 (no errors). But tcsh does output the error (without outputting its name, though):

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

Error messages

In general, the first item in the error message should be the executing process or function (your shell tries to execute ::, hence the error message comes from the shell). For instance, here the executing process is stat:

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

In fact, POSIX defines the perror() function, which according to the documentation takes a string argument, then outputs error message after colon, and then newline. Quote:

The perror() function shall map the error number accessed through the symbol errno to a language-dependent error message, which shall be written to the standard error stream as follows:

  • First (if s is not a null pointer and the character pointed to by s is not the null byte), the string pointed to by s followed by a colon and a <space>.

  • Then an error message string followed by a <newline>.

And the string argument to perror() technically could be anything, but of course for clarity it's typically the function name or argv[0].

By contrast, GNU has its own set of functions and variables for error handling, which a programmer can use with fprintf() to stderr stream. As one of the examples on the linked page shows, something like this could be done:

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

Historical note

In old Unix and Thompson shell, : was used with goto statement (which according to user named Perderabo on this thread wasn't a shell built-in). Quote from the manual:

The entire command file is searched for a line beginning with a : as the first non-blank character, followed by one or more blanks, and then the label. If such a line is found, goto repositions the command-file offset to the line after the label and exits. This causes the shell to transfer to the labelled line.

So you could do something like this to make an infinite loop script:

: repeat  echo "Hello World"  goto repeat  


Solution:2

The last colon is just part of the default "not found" message:

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

The reason a single colon produces nothing is that : is a valid command - although it does nothing (except return TRUE). From the SHELL BUILTIN COMMANDS section of man bash:

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

You will sometimes see it in constructions like

while :  do    something  done  

See for example What purpose does the colon builtin serve?


Solution:3

Try any other non-existent command and you'll see that the : serves its normal purpose in English:

$ ---  ---: command not found  


Solution:4

The added colon is part of the error message itself. If one types cd ow it results in bash: cd: ow: No such file or directory, which shows that the error is putting in the extra colon : No such file or directory


Solution:5

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

the 3rd is a spacer from formatting

in bash a : is an empty line void instruction


Solution:6

you get 3 colons because the error format contains a colon:

bash: <command>: command not found  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »