:
is a shell builtin command inherited from the Bourne Shell.
It does nothing beyond expanding arguments and performing redirection and has return status zero.
:
is a no-op operator similar to true
and false
.
In fact, command true
and :
both use the same function int colon_builtin()
underneath.
Parameter expansions
Shell’s parameter expansions are used to check and modify parameters.
Below illustrated how :
is used in parameter expansion by setting a default value combined with :
.
$ cat ./colon_script.sh
#!/usr/bin/env bash
read -p "Enter your name: " name
: ${name:=John Doe} # if the user entered an empty string
echo "$name"
$ ./colon_script.sh
Enter your name:
John Doe
$
If :
is omitted, the default value is passed and treated as a command.
]$ ./colon_script.sh
Enter your name:
./colon_script.sh: line 3: John: command not found
John Doe
John Doe
is still printed as the value has been assigned to variable name
.
More on Parameter expansion substitution
Use a default value
${parameter:-word}
If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.
Example:
#!/usr/bin/env bash
read -p "Enter your address (Press enter to not input address): " address
echo "You address is ${address:-unknown}."
The script will print “You address is unknown.” when enter
is pressed and no input is given. The default value is used on expansion time, it is not assigned to the parameter.
Assign a default value
${PARAMETER:=WORD}
If parameter is unset or null, the expansion of word is assigned to parameter. The value of parameter is then substituted. Positional parameters and special parameters may not be assigned to in this way.
Example:
#!/usr/bin/env bash
read -p "Enter your address (Press enter to not input address): " address
echo "You address is ${address:=unknown}."
echo "Checking. You address is really: $address ."
Here the default text is expanded and assigned to the parameter.
Use an alternate value
${parameter:+word}
If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substituted.
This form expands to nothing if the parameter is unset or empty. If it is set, it does not expand to the parameter’s value, but to some text you can specify
Example:
$ cat ./home.sh
#!/usr/bin/env bash
echo "Your home is ${HOME:+ - This text will be printed since $HOME is set}."
$ ./home.sh
Your home is - This text will be printed since /home/zain is set.
Replace true by :
The usual way to do infinite loop in bash is using the true
command in a while loop.
#!/usr/bin/env bash
while true
do
# ...
done
Alternatively, we can use :
instead of true
to create an infinite loop.
#!/usr/bin/env bash
while : ; do
# ....
done
just a : as first line in a shell
I came across a this forum where user smehra
were working on porting some shell script to Solaris and stumbled on :
as the first line instead of the usual shebang and wanted to know more about it.
User Perderabo
introduced a very useful background about the c shell, Bourne shell and comments, which is as follows:
When the Bourne shell was introduced, it did not have any way to handle comments. It did have the : command which does nothing. So people used the : command as a poor man’s comment. Like this:
: This is a comment.
This was better than nothing, but these “comments” have syntax restrictions. And they can have side effects that are persist past the statement.
Then Bill Joy introduced the c shell. It had the # syntax for comments. In these days, the shell had to run shell scripts. The kernel did not yet recognize the “#! /path/to/interpreter”. Bill Joy wanted his shell to be able to run both sh scripts and csh scripts. So he had to tell them apart. His solution was to assume that all scripts will start with a comment. So if the first character was a “:”, it was a sh script. And if the first character was a “#”, it was a csh script.
But then Steve Bourne added in the # syntax to sh. That broke the csh solution. The fix to this problem was to let the kernel handle shell scripts. That is where the “#!” syntax came in.
colon instead of shebang
Using :
instead of the shebang works fine.
$ cat ./colon_test.sh
:
echo "Hello World!"
$ ./colon_test.sh
Hello World!
Resources
https://askubuntu.com/questions/549608/what-is-the-point-of-the-bash-null-operator-colon
https://www.unix.com/shell-programming-and-scripting/10193-just-first-line-shell.html
https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html