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?

2

3 Answers 3

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 :.

3
  • 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
    Commented Mar 21, 2012 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. Commented Mar 21, 2012 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
    Commented Jun 25, 2012 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.

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
4
  • That's a useful distinction. I've even seen it in action, in a very confusing form, to avoid duplication when setting default values: : "${VARIABLE:=DEFAULT_VALUE}".
    – l0b0
    Commented Sep 25, 2022 at 13:47
  • @l0b0, using ${var:=value} is unrelated, though, it'd work with true also. (Try e.g. unset foo; true "${foo:=value}"; echo $foo with true vs. :.) The standard text only mentions variable assignments before the command --those that would end up as env vars for the launched command-- not expansions within the command line.
    – ilkkachu
    Commented Sep 25, 2022 at 13:55
  • 1
    See also sh -c ': > /; echo x' vs sh -c 'true > /; echo x' and Which is more idiomatic in a bash script: `|| true` or `|| :`? Commented Sep 25, 2022 at 14:00
  • @StéphaneChazelas Updated my answer to include this aspect too. Thank you!
    – Karolis
    Commented Sep 25, 2022 at 17:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .