Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I've hacked on a lot of shell scripts, and sometimes the simplest things baffle me. Today I ran across a script that made extensive use of the : (colon) bash builtin.

The documenation seems simple enough:

: (a colon)  
     : [arguments]  

Do nothing beyond expanding arguments and performing redirections. The return status is zero.

However I have only previously seen this used in demonstrations of shell expansion. The use case in the script I ran across made extensive use of this structure:

if [ -f ${file} ]; then
    grep some_string ${file} >> otherfile || :
    grep other_string ${file} >> otherfile || :
fi

There were actually hundreds of greps, but they are just more of the same. No other input/output redirects are presentother than the simple structure above. No return values are checked later in the script.

I am reading this as a useless contstruct that says "or do nothing". What purpose could ending these greps with "or do nothing" serve? In what case would this construct cause a different outcome than simply leaving off the || : from all instances?

share|improve this question
5  
One possible purpose I can see is to use : as an alternative to true. Perhaps errexit is set and the author doesn't care about the exit status of some commands. –  jw013 Feb 14 '12 at 18:42
3  
Heh, nearly identical question on SO –  jw013 Feb 14 '12 at 18:49

7 Answers 7

up vote 10 down vote accepted

It appears the :s in your script are being used in lieu of true. If grep doesn't find a match in the file, it will return a nonzero exit code; as jw013 mentions in a comment, if errexit is set, probably by -e on the shebang line, the script would exit if any of the greps fail to find a match. Clearly, that's not what the author wanted, so (s)he added || : to make the exit status of that particular compound command always zero, like the more common (in my experience) || true/|| /bin/true.

share|improve this answer
    
Duh. This was in the concept of an RPM build script, and while I didn't see any exit code checking inside the script, I forgot to consider that the parent process might be watching. –  Caleb Feb 14 '12 at 20:55
3  
If that's the case, I'd call it poor scripting practice. It's functionally equivalent to using true instead, but the semantic intent is much clearer with true. : is more suitable when an explicit NOP is desired. –  jw013 Apr 27 '12 at 6:12

I can think of two places I've used : in the past.

while :
do
     shell commands
     some exit condition
done

That is a forever-loop.

function doSomethingStub {
    :
}

Put in a stub function, just to get top level flow of control correct.

One use I've seen back in the Old Days: Instead of a #!/bin/sh (or whatever) line, you'd see a : line. Some of the older Real Unix kernels or Real Unix shells would use that to mean "I'm a shell script, have sh run me". As I recall this was just when csh was making inroads as a common interactive shell.

share|improve this answer
    
+1 for older than the shebang usage –  Arcege Feb 14 '12 at 22:46
    
@BruceEdiger: Do you have a reference to the "shecolon" line? –  l0b0 Mar 22 '12 at 8:20
2  
Finally found a ": at the beginning of a script" reference and explanation: faqs.org/faqs/unix-faq/faq/part3/section-16.html –  Bruce Ediger Mar 22 '12 at 20:22

The : builtin is also useful with the Bash "assign default values" shell expansion, where the expansion is often used solely for the side effect and the value expanded is thrown away:

# assign FOO=bar iff FOO is unset
: ${FOO:=bar}
share|improve this answer

I seem to recall that early versions of the shell didn't have a comment syntax. A line starting with : (which probably would have been an actual executable, similar to /bin/true) would have been the best alternative.

Here's a man page for the ancient Thompson shell (no relation); there's no mention of any comment syntax.

share|improve this answer
1  
The origin of : was in fact a label indicator for the goto command, in some ancient shell (I don't know which). A label : something could indeed be used as a comment, if there was no matching goto. The practice stuck even after goto disappeared. –  Gilles Feb 15 '12 at 6:29

The : built-in was already in the Thompson shell — it's documented for Unix V6 in 1975. In the Thompson shell, : indicated a label for the goto command. If you never attempted to call goto on a line beginning with , that line was effectively a comment.

The Bourne shell, the ancestor of Bourne/POSIX shells as we know them, never had a goto that I know of, but retained : as a no-op command (it was already present in Unix V7).

share|improve this answer

Dug out an old reference: "The UNIX Programming Environment" (c) 1984 by Kernighan and Pike.

Page 147 (Shell Programming) says this:

":" is a shell built-in command that does nothing but elevate its arguments and return "true". Instead [referring to a script example], we could have used true, which merely returns a true exit status. (There is also a false command.) But ':' is more efficient than true because it does not execute a command from the file system. [Italics/emphasis is mine.]

share|improve this answer

":" is handy for debugging.

DEBUGLOG=": debugfunction"

statement
statement
$DEBUGLOG arg1 arg2 ...
statement
statement

Running normally the debugfunction is never executed so sh just steps over the noop (variables and wildcards are expanded though). If more in depth debugging is required, remove the noop from the variable and debugfunction is called with whatever arguments are required.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.