17

In bash:

$ type :
: is a shell builtin
$ type true
true is a shell builtin

Looks like they are the same, but they don't give the same system trace:

$ strace :
strace: :: command not found
$ strace true
execve("/bin/true", ["true"], [/* 82 vars */]) = 0
[snip]
exit_group(0)                           = ?

I tried diffing strace bash -c : 2>:.txt and strace bash -c true 2>true.txt, but couldn't find any differences between them except for the memory locations.

In dash:

$ type :
: is a special shell builtin
$ type true
true is a shell builtin

OK, so they are not the same. help : and help true aren't very useful, and they return the same in bash and dash. Is there any practical difference at all between them, except that : saves three bytes and makes scripts less readable?

l0b0
  • 51,350

3 Answers3

28

There's no real difference in behavior. Both commands do nothing and exit with a successful status. : emphasizes doing nothing; true emphasizes the successful status.

strace true works because true is both a shell builtin and an external command (/bin/true); : is only a shell builtin (there's no /bin/: -- though there could be, and probably was on very old Unix systems). In bash, try

type -a :
type -a true

The reasons that both exist are historical. If I recall correctly, some very early shells didn't have a comment syntax, so the do-nothing : command was used instead.

There is some internal difference in dash. Looking through the source, available at git://git.kernel.org/pub/scm/utils/dash/dash.git, shows some different code paths in eval.c, but I haven't been able to produce any visibly different behavior other than the word special in the output of type :.

  • 8
    Additionally, early versions of UNIX did not have /bin/true or /bin/false. Also the : command is sometimes used for the argument processing side effects: : ${num_times:=10}. – Arcege Mar 21 '12 at 18:16
  • 7
    : was originally a label indicator, back in an ancestor of the Bourne shell that had goto. Apparently : was abused as a comment indicator and stuck. – Gilles 'SO- stop being evil' Mar 21 '12 at 23:40
  • 1
    The behavior of : as a label indicator for goto was preserved in Microsoft's pseudo-Unix command line clone, command.com, and remains in its successor cmd.exe, as does the practice of abusing :: for a line comment. – Sorpigal Jun 25 '12 at 12:19
8

They're identical in Bash. Look at builtins/colon.def in the Bash-4.2 source code.

In your command strace true you are actually running the binary /bin/true instead of the bash built-in true.

Jodie C
  • 1,879
6

The difference between the commands are that by definition : is a special built-in utility whereas true is a regular built-in utility in POSIX compliant shells.

According to POSIX specification, special built-ins are treated slightly differently in a way that:

variable assignments preceding the invocation of a special built-in utility remain in effect after the built-in completes; this shall not be the case with a regular built-in or other utility.

This can be illustrated in POSIX compliant shells as follows:

$ VAR=FOO
$ VAR=BAR :
$ echo "$VAR"
BAR
$ VAR=FOO
$ VAR=BAR true
$ echo "$VAR"
FOO

Another aspect of difference is that:

an error in a special built-in utility may cause a shell executing that utility to abort, while an error in a regular built-in utility shall not cause a shell executing that utility to abort.

Example code in action:

$ ( : > ""; echo "You won't see this!" )
sh: 1: cannot create : Directory nonexistent
$  echo "Exit code: $?"
Exit code: 2
$ ( true > ""; echo "Hello!" )
sh: 1: cannot create : Directory nonexistent
Hello!
$ echo "Exit code: $?"
Exit code: 0
Karolis
  • 161